Browse Source

Merge branch 'magSlideShowSource'

master
c-mendoza 8 years ago
parent
commit
06f9f1aa87
  1. 8
      .gitignore
  2. 23
      example/CMakeLists.txt
  3. 3
      example/addons.make
  4. 30
      example/bin/data/ofxpimapper.xml
  5. 1545
      example/example.xcodeproj/project.pbxproj
  6. 19
      example/example.xcodeproj/xcshareddata/xcschemes/example Debug.xcscheme
  7. 19
      example/example.xcodeproj/xcshareddata/xcschemes/example Release.xcscheme
  8. 4
      example/openFrameworks-Info.plist
  9. 2
      example/src/main.cpp
  10. 25
      example/src/ofApp.cpp
  11. 38
      example/src/ofApp.h
  12. 45
      src/Application/Application.cpp
  13. 35
      src/Application/Application.h
  14. 209
      src/Sources/magSlide.cpp
  15. 263
      src/Sources/magSlide.h
  16. 498
      src/Sources/magSlideShowSource.cpp
  17. 161
      src/Sources/magSlideShowSource.h
  18. 60
      src/Sources/magSlideTransition.cpp
  19. 129
      src/Sources/magSlideTransition.h
  20. 76
      src/Sources/magSlideTransitionFactory.cpp
  21. 41
      src/Sources/magSlideTransitionFactory.h
  22. 4
      src/ofxPiMapper.cpp
  23. 21
      src/ofxPiMapper.h

8
.gitignore

@ -105,3 +105,11 @@ Desktop.ini
*.log *.log
*.sql *.sql
*.sqlite *.sqlite
example/cmake-build-debug/
example/\.idea/
example/cmake-build-release/
example/example\.xcodeproj/xcshareddata/xcschemes/

23
example/CMakeLists.txt

@ -4,6 +4,7 @@
# ===================== CMake Settings =================== # ===================== CMake Settings ===================
# ======================================================== # ========================================================
cmake_minimum_required( VERSION 3.3 ) cmake_minimum_required( VERSION 3.3 )
project( openframeworks ) project( openframeworks )
# ======================================================== # ========================================================
@ -17,21 +18,23 @@ set( APP_NAME example_ofxPiMapper )
set( OF_DIRECTORY_BY_USER "../../.." ) set( OF_DIRECTORY_BY_USER "../../.." )
# --------------------- Source Files --------------------- # --------------------- Source Files ---------------------
file( GLOB_RECURSE
APP_SRC
"src/*.cpp"
)
set( ${APP_NAME}_SOURCE_FILES set( ${APP_NAME}_SOURCE_FILES
src/main.cpp ${APP_SRC} )
src/ofApp.cpp
src/CrossSource.cpp
src/CustomSource.cpp
src/Settings.cpp)
# ------------------------ AddOns ----------------------- # ------------------------ AddOns -----------------------
set( OFX_ADDONS_ACTIVE set( OFX_ADDONS_ACTIVE
ofxXmlSettings ofxXmlSettings
ofxGui ofxGui
ofxPiMapper ofxPiMapper
ofxIO # ofxIO
) )
# ========================================================================= # =========================================================================
# ============================== OpenFrameworks =========================== # ============================== OpenFrameworks ===========================

3
example/addons.make

@ -1,4 +1,3 @@
ofxGui
ofxPiMapper ofxPiMapper
ofxXmlSettings ofxXmlSettings
ofxGui
ofxOMXPlayer

30
example/bin/data/ofxpimapper.xml

@ -2,16 +2,16 @@
<surface type="0"> <surface type="0">
<vertices> <vertices>
<vertex> <vertex>
<x>250.000000000</x> <x>244.000000000</x>
<y>138.187255859</y> <y>151.187255859</y>
</vertex> </vertex>
<vertex> <vertex>
<x>403.625549316</x> <x>397.625549316</x>
<y>291.812774658</y> <y>304.812774658</y>
</vertex> </vertex>
<vertex> <vertex>
<x>96.374511719</x> <x>90.374511719</x>
<y>291.812774658</y> <y>304.812774658</y>
</vertex> </vertex>
</vertices> </vertices>
<texCoords> <texCoords>
@ -36,20 +36,20 @@
<surface type="1"> <surface type="1">
<vertices> <vertices>
<vertex> <vertex>
<x>425.565002441</x> <x>305.332824707</x>
<y>144.782531738</y> <y>158.923416138</y>
</vertex> </vertex>
<vertex> <vertex>
<x>718.434936523</x> <x>823.889770508</x>
<y>144.782531738</y> <y>135.275909424</y>
</vertex> </vertex>
<vertex> <vertex>
<x>718.434936523</x> <x>883.853393555</x>
<y>291.217407227</y> <y>670.724243164</y>
</vertex> </vertex>
<vertex> <vertex>
<x>425.565002441</x> <x>241.146575928</x>
<y>291.217407227</y> <y>656.366699219</y>
</vertex> </vertex>
</vertices> </vertices>
<texCoords> <texCoords>
@ -72,7 +72,7 @@
</texCoords> </texCoords>
<source> <source>
<source-type>fbo</source-type> <source-type>fbo</source-type>
<source-name>Custom FBO Source</source-name> <source-name>Slide Show Source</source-name>
</source> </source>
<properties> <properties>
<perspectiveWarping>1</perspectiveWarping> <perspectiveWarping>1</perspectiveWarping>

1545
example/example.xcodeproj/project.pbxproj

File diff suppressed because it is too large

19
example/example.xcodeproj/xcshareddata/xcschemes/example Debug.xcscheme

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0720" LastUpgradeVersion = "0600"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,10 +23,10 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables> <Testables>
</Testables> </Testables>
<MacroExpansion> <MacroExpansion>
@ -38,21 +38,17 @@
ReferencedContainer = "container:example.xcodeproj"> ReferencedContainer = "container:example.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<BuildableProductRunnable <BuildableProductRunnable>
runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2" BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2"
@ -65,13 +61,12 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Debug"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<BuildableProductRunnable <BuildableProductRunnable>
runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2" BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2"

19
example/example.xcodeproj/xcshareddata/xcschemes/example Release.xcscheme

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0720" LastUpgradeVersion = "0600"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -23,10 +23,10 @@
</BuildActionEntries> </BuildActionEntries>
</BuildAction> </BuildAction>
<TestAction <TestAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Release">
<Testables> <Testables>
</Testables> </Testables>
<MacroExpansion> <MacroExpansion>
@ -38,21 +38,17 @@
ReferencedContainer = "container:example.xcodeproj"> ReferencedContainer = "container:example.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<BuildableProductRunnable <BuildableProductRunnable>
runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2" BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2"
@ -65,13 +61,12 @@
</AdditionalOptions> </AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES" shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = "" savedToolIdentifier = ""
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES"> debugDocumentVersioning = "YES">
<BuildableProductRunnable <BuildableProductRunnable>
runnableDebuggingMode = "0">
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2" BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2"

4
example/openFrameworks-Info.plist

@ -6,8 +6,6 @@
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>${ICON}</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>cc.openFrameworks.ofapp</string> <string>cc.openFrameworks.ofapp</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
@ -18,5 +16,7 @@
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>CFBundleIconFile</key>
<string>${ICON}</string>
</dict> </dict>
</plist> </plist>

2
example/src/main.cpp

@ -17,6 +17,6 @@ int main(int argc, char * argv[]){
Settings::instance()->setFullscreen(fullscreen); Settings::instance()->setFullscreen(fullscreen);
ofSetupOpenGL(800, 450, OF_WINDOW); ofSetupOpenGL(1024, 768, OF_WINDOW);
ofRunApp(new ofApp()); ofRunApp(new ofApp());
} }

25
example/src/ofApp.cpp

@ -14,15 +14,38 @@ void ofApp::setup(){
// a surface in XML settings. // a surface in XML settings.
crossSource = new CrossSource(); crossSource = new CrossSource();
customSource = new CustomSource(); customSource = new CustomSource();
// Create the slide show source.
slideShowSource = new magSlideShowSource();
// Create the settings struct for the slide show.
// Initialize the slide show with our settings.
// If it fails, initialize from default settings
// Register our sources:
piMapper.registerFboSource(crossSource); piMapper.registerFboSource(crossSource);
piMapper.registerFboSource(customSource); piMapper.registerFboSource(customSource);
piMapper.registerFboSource(slideShowSource);
piMapper.setup(); piMapper.setup();
// Slide show needs to be loaded after piMapper is set up:
if (!slideShowSource->loadFromXml())
{
ofLogNotice("setup") << "loading magSlideShowSource XML settings failed. Initializing from default values";
magSlideShowSource::Settings sets;
slideShowSource->initialize(sets);
}
// The info layer is hidden by default, press <i> to toggle // The info layer is hidden by default, press <i> to toggle
// piMapper.showInfo(); // piMapper.showInfo();
ofSetFullscreen(Settings::instance()->getFullscreen()); ofSetFullscreen(Settings::instance()->getFullscreen());
ofSetEscapeQuitsApp(false); ofSetEscapeQuitsApp(false);
ofSetLogLevel(OF_LOG_VERBOSE);
slideShowSource->play();
} }
void ofApp::update(){ void ofApp::update(){

38
example/src/ofApp.h

@ -6,24 +6,28 @@
#include "CustomSource.h" #include "CustomSource.h"
#include "CrossSource.h" #include "CrossSource.h"
#include "VideoSource.h" #include "VideoSource.h"
#include "magSlideShowSource.h"
class ofApp : public ofBaseApp { class ofApp : public ofBaseApp
public: {
void setup(); public:
void update(); void setup();
void draw(); void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper piMapper; void keyPressed(int key);
void keyReleased(int key);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button);
ofxPiMapper piMapper;
// By using a custom source that is derived from FboSource
// you will be able to see the source listed in sources editor
CustomSource *customSource;
CrossSource *crossSource;
magSlideShowSource *slideShowSource;
// By using a custom source that is derived from FboSource
// you will be able to see the source listed in sources editor
CustomSource * customSource;
CrossSource * crossSource;
}; };

45
src/Application/Application.cpp

@ -7,16 +7,16 @@ namespace piMapper {
Application::Application(){ Application::Application(){
_keySequence = ""; _keySequence = "";
_surfaceManager.setMediaServer(&_mediaServer); _surfaceManager.setMediaServer(&_mediaServer);
// Set initial mode // Set initial mode
setState(PresentationMode::instance()); setState(PresentationMode::instance());
ofHideCursor(); ofHideCursor();
ofAddListener(Gui::instance()->jointPressedEvent, this, &Application::onJointPressed); ofAddListener(Gui::instance()->jointPressedEvent, this, &Application::onJointPressed);
ofAddListener(Gui::instance()->surfacePressedEvent, this, &Application::onSurfacePressed); ofAddListener(Gui::instance()->surfacePressedEvent, this, &Application::onSurfacePressed);
ofAddListener(Gui::instance()->backgroundPressedEvent, this, &Application::onBackgroundPressed); ofAddListener(Gui::instance()->backgroundPressedEvent, this, &Application::onBackgroundPressed);
ofAddListener(Gui::instance()->guiEvent, this, &Application::onGuiEvent); ofAddListener(Gui::instance()->guiEvent, this, &Application::onGuiEvent);
_lastSaveTime = 0.0f; _lastSaveTime = 0.0f;
_autoSaveInterval = 60.0f; _autoSaveInterval = 60.0f;
} }
@ -35,7 +35,7 @@ void Application::setup(){
throw runtime_error("ofxPiMapper: Failed to create default settings file."); throw runtime_error("ofxPiMapper: Failed to create default settings file.");
} }
} }
// Setup all states. // Setup all states.
PresentationMode::instance()->setup(this); PresentationMode::instance()->setup(this);
TextureMappingMode::instance()->setup(this); TextureMappingMode::instance()->setup(this);
@ -49,7 +49,7 @@ void Application::setup(){
void Application::update(){ void Application::update(){
_mediaServer.update(); _mediaServer.update();
_state->update(this); _state->update(this);
// Autosave, do it only of the mode is not presentation mode // Autosave, do it only of the mode is not presentation mode
if(_state != PresentationMode::instance()){ if(_state != PresentationMode::instance()){
float timeNow = ofGetElapsedTimef(); float timeNow = ofGetElapsedTimef();
@ -72,7 +72,7 @@ void Application::draw(){
// Here we handle application state changes only // Here we handle application state changes only
void Application::onKeyPressed(ofKeyEventArgs & args){ void Application::onKeyPressed(ofKeyEventArgs & args){
// Key sequence based commands. Last three keys are taken into account. // Key sequence based commands. Last three keys are taken into account.
_keySequence += args.key; _keySequence += args.key;
if(_keySequence.size() >= 3){ if(_keySequence.size() >= 3){
@ -100,11 +100,11 @@ void Application::onKeyPressed(ofKeyEventArgs & args){
case OF_KEY_SHIFT: case OF_KEY_SHIFT:
_shiftKeyDown = true; _shiftKeyDown = true;
break; break;
case '/': case '/':
_shiftKeyDown = !_shiftKeyDown; _shiftKeyDown = !_shiftKeyDown;
break; break;
case '1': case '1':
setPresentationMode(); setPresentationMode();
break; break;
@ -132,7 +132,7 @@ void Application::onKeyPressed(ofKeyEventArgs & args){
case 'z': case 'z':
undo(); undo();
break; break;
case 'n': case 'n':
setNextPreset(); setNextPreset();
break; break;
@ -325,14 +325,14 @@ void Application::selectPrevVertex(){
void Application::selectVertex(int surface, int vertex){ void Application::selectVertex(int surface, int vertex){
if(getSurfaceManager()->size()){ if(getSurfaceManager()->size()){
// TODO: use one command instead of two // TODO: use one command instead of two
getCmdManager()->exec( getCmdManager()->exec(
new SelSurfaceCmd( new SelSurfaceCmd(
getSurfaceManager(), getSurfaceManager(),
getSurfaceManager()->getSurface(surface))); getSurfaceManager()->getSurface(surface)));
getCmdManager()->exec( getCmdManager()->exec(
new SelVertexCmd( new SelVertexCmd(
getSurfaceManager(), getSurfaceManager(),
@ -398,7 +398,7 @@ void Application::moveLayerUp(){
getSurfaceManager()->getActivePreset()->size() - 1)){ getSurfaceManager()->getActivePreset()->size() - 1)){
return; return;
} }
getCmdManager()->exec( getCmdManager()->exec(
new MvLayerUpCmd( new MvLayerUpCmd(
getSurfaceManager()->getActivePreset(), getSurfaceManager()->getActivePreset(),
@ -412,7 +412,7 @@ void Application::moveLayerDown(){
getSurfaceManager()->getActivePreset()->at(0)){ getSurfaceManager()->getActivePreset()->at(0)){
return; return;
} }
getCmdManager()->exec( getCmdManager()->exec(
new MvLayerDnCmd( new MvLayerDnCmd(
getSurfaceManager()->getActivePreset(), getSurfaceManager()->getActivePreset(),
@ -463,6 +463,19 @@ void Application::setNextSource(){
} }
} }
void Application::setFboSource(string sourceId){
if(getSurfaceManager()->getSelectedSurface() != 0){
getCmdManager()->exec(
new SetSourceCmd(
SourceType::SOURCE_TYPE_FBO,
sourceId,
getSurfaceManager()->getSelectedSurface(),
&Gui::instance()->getSourcesEditorWidget()));
}else{
getCmdManager()->exec(new SelNextSurfaceCmd(getSurfaceManager()));
}
}
void Application::addGridRow(){ void Application::addGridRow(){
if(getSurfaceManager()->getSelectedSurface() != 0){ if(getSurfaceManager()->getSelectedSurface() != 0){
if(getSurfaceManager()->getSelectedSurface()->getType() == if(getSurfaceManager()->getSelectedSurface()->getType() ==
@ -519,7 +532,7 @@ void Application::togglePause(){
if(getSurfaceManager()->getSelectedSurface() == 0){ if(getSurfaceManager()->getSelectedSurface() == 0){
return; return;
} }
if(getSurfaceManager()->getSelectedSurface()->getSource()->getType() == if(getSurfaceManager()->getSelectedSurface()->getSource()->getType() ==
SourceType::SOURCE_TYPE_VIDEO){ SourceType::SOURCE_TYPE_VIDEO){
getCmdManager()->exec( getCmdManager()->exec(
@ -535,7 +548,7 @@ void Application::moveTexCoord(int texCoordIndex, ofVec2f by){
getCmdManager()->exec(new MvAllTexCoordsCmd( getCmdManager()->exec(new MvAllTexCoordsCmd(
getSurfaceManager()->getSelectedSurface(), getSurfaceManager()->getSelectedSurface(),
&Gui::instance()->getTextureEditorWidget())); &Gui::instance()->getTextureEditorWidget()));
Gui::instance()->getTextureEditorWidget().moveSelection(by); Gui::instance()->getTextureEditorWidget().moveSelection(by);
} }
} }

35
src/Application/Application.h

@ -66,22 +66,22 @@ class Application {
void setup(); void setup();
void update(); void update();
void draw(); void draw();
void onKeyPressed(ofKeyEventArgs & args); void onKeyPressed(ofKeyEventArgs & args);
void onKeyReleased(ofKeyEventArgs & args); void onKeyReleased(ofKeyEventArgs & args);
// We use this to pass mouse events into the GUI layer // We use this to pass mouse events into the GUI layer
void onMousePressed(ofMouseEventArgs & args); void onMousePressed(ofMouseEventArgs & args);
void onMouseReleased(ofMouseEventArgs & args); void onMouseReleased(ofMouseEventArgs & args);
void onMouseDragged(ofMouseEventArgs & args); void onMouseDragged(ofMouseEventArgs & args);
// Then we catch GUI events with this one and create commands // Then we catch GUI events with this one and create commands
void onJointPressed(GuiJointEvent & e); void onJointPressed(GuiJointEvent & e);
void onSurfacePressed(GuiSurfaceEvent & e); void onSurfacePressed(GuiSurfaceEvent & e);
void onBackgroundPressed(GuiBackgroundEvent & e); void onBackgroundPressed(GuiBackgroundEvent & e);
void onGuiEvent(GuiEvent & e); void onGuiEvent(GuiEvent & e);
void addFboSource(FboSource & fboSource); void addFboSource(FboSource & fboSource);
void addFboSource(FboSource * fboSource); void addFboSource(FboSource * fboSource);
void createSurface(SurfaceType type); void createSurface(SurfaceType type);
@ -97,7 +97,7 @@ class Application {
SurfaceManager * getSurfaceManager(){ return &_surfaceManager; } SurfaceManager * getSurfaceManager(){ return &_surfaceManager; }
CmdManager * getCmdManager(){ return &_cmdManager; } CmdManager * getCmdManager(){ return &_cmdManager; }
MediaServer * getMediaServer(){ return &_mediaServer; } MediaServer * getMediaServer(){ return &_mediaServer; }
// Command executors // Command executors
void selectSurface(int i); void selectSurface(int i);
void selectNextSurface(); void selectNextSurface();
@ -107,14 +107,14 @@ class Application {
void selectVertex(int surface, int vertex); void selectVertex(int surface, int vertex);
void selectNextTexCoord(); void selectNextTexCoord();
void selectPrevTexCoord(); void selectPrevTexCoord();
/* /*
Context sensitive move. Context sensitive move.
Moves vertex when in projection mapping mode. Moves vertex when in projection mapping mode.
Moves texture coordinate when in texture mapping mode. Moves texture coordinate when in texture mapping mode.
*/ */
void moveSelection(ofVec2f by); void moveSelection(ofVec2f by);
void setPresentationMode(); void setPresentationMode();
void setTextureMode(); void setTextureMode();
void setProjectionMode(); void setProjectionMode();
@ -125,6 +125,7 @@ class Application {
void scaleDown(); void scaleDown();
void duplicateSurface(); void duplicateSurface();
void setNextSource(); void setNextSource();
void setFboSource(string sourceId);
void addGridRow(); void addGridRow();
void addGridColumn(); void addGridColumn();
void removeGridRow(); void removeGridRow();
@ -135,33 +136,33 @@ class Application {
// Make it so that other parts of the application react to the change. // Make it so that other parts of the application react to the change.
void undo(); void undo();
void deselect(); void deselect();
void setPreset(unsigned int i); void setPreset(unsigned int i);
void setNextPreset(); void setNextPreset();
// System commands // System commands
void reboot(); void reboot();
void shutdown(); void shutdown();
protected: protected:
void setState(ApplicationBaseMode * st); void setState(ApplicationBaseMode * st);
private: private:
friend class ApplicationBaseMode; friend class ApplicationBaseMode;
friend class SetApplicationModeCmd; friend class SetApplicationModeCmd;
ApplicationBaseMode * _state; ApplicationBaseMode * _state;
CmdManager _cmdManager; CmdManager _cmdManager;
MediaServer _mediaServer; MediaServer _mediaServer;
SurfaceManager _surfaceManager; SurfaceManager _surfaceManager;
Info _info; Info _info;
bool _shiftKeyDown; bool _shiftKeyDown;
float _lastSaveTime; float _lastSaveTime;
float _autoSaveInterval; float _autoSaveInterval;
string _keySequence; string _keySequence;
}; };

209
src/Sources/magSlide.cpp

@ -0,0 +1,209 @@
//
// magSlide.cpp
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#include "magSlide.h"
#include "magSlideTransition.h"
#pragma mark magSlide
int magSlide::idCount = 0;
magSlide::magSlide(std::string type)
{
this->type = type;
position = ofPoint(0, 0);
id = magSlide::idCount;
magSlide::idCount++;
}
void magSlide::update(u_int64_t deltaTime)
{
transition->update(deltaTime);
runningTime += deltaTime;
switch (slideState)
{
// case SlideState::BuildIn:
// if (runningTime >= buildInDuration)
// {
// setState(Normal);
// activeTransition = nullptr;
// }
// break;
case SlideState::Normal:
if (runningTime >= buildOutStartTime)
{
setState(BuildOut);
}
break;
case SlideState::BuildOut:
if (runningTime >= endTime)
{
setState(Complete);
}
break;
}
}
void magSlide::setSize(float w, float h)
{
width = w;
height = h;
}
void magSlide::setResizeOption(magSlide::ResizeOptions resizeOption)
{
this->resizeOption = resizeOption;
}
magSlide::ResizeOptions magSlide::getResizeOption() const
{
return resizeOption;
}
void magSlide::setDuration(u_int64_t duration)
{
this->duration = duration;
}
void magSlide::setState(SlideState state)
{
// Don't do anything if the new state is the same
// as the current one:
if (slideState == state) return;
slideState = state;
ofEventArgs args;
ofNotifyEvent(slideStateChangedEvent, args, this);
if (slideState == Complete)
{
ofNotifyEvent(slideCompleteEvent, args, this);
}
}
void magSlide::setTransitionDuration(u_int64_t tDuration)
{
buildOutDuration = tDuration;
}
const std::string magSlide::getSlideStateName()
{
switch (slideState)
{
// case SlideState::BuildIn:
// return "BuildIn";
case SlideState::BuildOut:
return "BuildOut";
case Normal:
return "Normal";
case SlideState::Complete:
return "Complete";
case SlideState::Off:
return "Off";
}
return "unknown";
}
void magSlide::start(u_int64_t startTime)
{
this->startTime = startTime;
runningTime = 0;
endTime = duration + buildOutDuration;
buildOutStartTime = endTime - buildOutDuration;
slideState = magSlide::SlideState::Normal;
// if (buildIn != nullptr)
// {
// activeTransition = buildIn;
// activeTransition->start();
// }
position.set(0, 0);
opacity = 255;
isComplete = false;
}
void magSlide::draw()
{
ofSetColor(255, opacity);
if(transition->isActive())
{
transition->draw();
}
}
////////////////////////////////////////////////////////
#pragma mark MAG_IMAGE_SLIDE
////////////////////////////////////////////////////////
magImageSlide::magImageSlide() : magSlide("magImageSlide") {}
magImageSlide::~magImageSlide() {}
void magImageSlide::setup(ofImage &image)
{
// Make a copy of the image:
this->image = ofImage(image);
image.setAnchorPercent(0.5, 0.5);
width = image.getWidth();
height = image.getHeight();
}
void magImageSlide::draw()
{
magSlide::draw();
image.draw(position, width, height);
}
////////////////////////////////////////////////////////
#pragma mark MAG_VIDEO_SLIDE
////////////////////////////////////////////////////////
magVideoSlide::magVideoSlide() : magSlide("magVideoSlide")
{}
magVideoSlide::~magVideoSlide()
{
videoPlayer.stop();
}
bool magVideoSlide::setup(ofFile &file, bool useVideoDuration)
{
bool success = videoPlayer.load(file.getAbsolutePath());
if (success)
{
videoPlayer.setAnchorPercent(0.5, 0.5);
if (useVideoDuration)
{
useVideoForDuration();
}
}
return success;
}
void magVideoSlide::update()
{
videoPlayer.update();
}
void magVideoSlide::draw()
{
magSlide::draw();
videoPlayer.draw(position.x, position.y, width, height);
}
void magVideoSlide::useVideoForDuration()
{
duration = u_int64_t((videoPlayer.getDuration()*1000)) - buildOutDuration;
}

263
src/Sources/magSlide.h

@ -0,0 +1,263 @@
//
// Created by Cristobal Mendoza on 11/9/17.
//
#ifndef MAGSLIDE_H
#define MAGSLIDE_H
#include "ofMain.h"
class magSlideTransition;
class magSlide
{
public:
magSlide(std::string type);
// ~magSlide();
virtual void update(u_int64_t deltaTime);
virtual void draw();
/**
* Sets the slide up for playback. This method must be
* called before displaying the slide.
* @param startTime
*/
void start(u_int64_t startTime);
enum ResizeOptions : short
{
/**
* No resizing applied, displays the slide in its native pixel dimensions.
* This is the default behavior.
*/
NoResize = 0,
/**
* Explicitly set a slide to display in its native dimension.
* None and NoResize result in the same output, but if you specify
* a default resizing option in your slideshow and you want a particular
* slide not to resize, you must specify this option. Otherwise the
* slide show option will apply.
*/
Native,
/**
* Sets width and height to match the source's.
* This will distort the slide if the aspect ratios
* don't match.
*/
Fit,
/**
* Resizes the largest dimension to the source's max,
* the other dimension is resized proportionally.
*/
FitProportionally,
/**
* Resizes the shortest dimensions to the source's max,
*/
FillProportionally,
};
enum SlideState : short
{
Off = 0,
// BuildIn,
Normal,
BuildOut,
Complete
};
const std::string &getType()
{ return type; }
float getWidth()
{ return width; }
float getHeight()
{ return height; }
float getOpacity() const
{
return opacity;
}
void setOpacity(float opacity)
{
magSlide::opacity = opacity;
}
/**
* Change the display size of a slide. This will implicitly
* set resizeOptions to ResizeOption.NoResize.
* This method does not resize the pixel source of the slide.
* @param w The new width
* @param h The new height
*/
virtual void setSize(float w, float h);
u_int64_t getDuration()
{
return duration;
}
/**
* Sets the display time of the slide, excluding
* builds (in or out)
* @param duration in milliseconds.
*/
void setDuration(u_int64_t duration);
/**
* Sets the duration of the buildIn and buildOut
* transitions. Transition times are added to the
* duration of the slide.
* @param tDuration in milliseconds.
*/
void setTransitionDuration(u_int64_t tDuration);
ResizeOptions getResizeOption() const;
void setResizeOption(ResizeOptions resizeOption);
SlideState getSlideState() const
{
return slideState;
}
bool isSlideComplete()
{ return isComplete; }
int getId()
{ return id; }
const std::string getSlideStateName();
//////////////////////////////
/// Events
//////////////////////////////
ofEvent<ofEventArgs> slideCompleteEvent;
ofEvent<ofEventArgs> slideStateChangedEvent;
friend class magSlideShowSource;
protected:
int id;
std::string type;
float width;
float height;
ofPoint position;
public:
const ofPoint &getPosition() const
{
return position;
}
void setPosition(const ofPoint &position)
{
magSlide::position = position;
}
void setPosition(float x, float y)
{
position.set(x, y);
}
protected:
float opacity = 255;
ResizeOptions resizeOption = NoResize;
SlideState slideState = Off;
bool isComplete = false;
// std::shared_ptr<magSlideTransition> buildIn = nullptr;
// std::shared_ptr<magSlideTransition> buildOut = nullptr;
std::shared_ptr<magSlideTransition> transition = nullptr;
public:
const shared_ptr<magSlideTransition> &getTransition() const
{
return transition;
}
protected:
/**
* The duration of the slide in millis, not counting builds
*/
u_int64_t duration;
/**
* The start time of the slide in milliseconds, in "local time".
* In practice, this means that the start time is always 0.
*/
u_int64_t startTime;
/**
* The end time of the slide in milliseconds, in "local time".
* The endTime is startTime + buildInDuration + duration + buildOutDuration.
*/
u_int64_t endTime;
/**
* The duration of the build in transition or effect, in milliseconds.
*/
// u_int64_t buildInDuration;
/**
* The duration of the build out transition or effect, in milliseconds.
*/
u_int64_t buildOutDuration;
/**
* The "local time" start of the build out transition. This time should also
* signal the enqueuing of the next slide, if applicable.
*/
u_int64_t buildOutStartTime;
/**
* The amount of time the slide has been displayed, in milliseconds.
* This constitutes the "local time" of the slide.
*/
u_int64_t runningTime;
void setState(SlideState state);
static int idCount;
};
class magImageSlide : public magSlide
{
public:
magImageSlide();
~ magImageSlide();
/**
* Sets up an image slide.
* @param image is copied into the member magImageSlide::image and is
* not modified in any way.
*/
void setup(ofImage &image);
void draw();
protected:
ofImage image;
};
class magVideoSlide : public magSlide
{
public:
magVideoSlide();
~magVideoSlide();
bool setup(ofFile &file, bool useVideoDuration = false);
void update();
void draw();
/**
* Sets the slide duration to the duration of the video.
* magSlide::duration will be changed by this call, so if you later
* change your mind you'll have to use magSlide::setDuration.
*/
void useVideoForDuration();
protected:
ofVideoPlayer videoPlayer;
};
#endif

498
src/Sources/magSlideShowSource.cpp

@ -0,0 +1,498 @@
//
// magSlideShowSource.cpp
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#include "magSlideShowSource.h"
#include "magSlideTransition.h"
#include "SettingsLoader.h"
#include "magSlideTransitionFactory.h"
magSlideShowSource::magSlideShowSource()
{
name = "Slide Show Source";
currentSlideIndex = 0;
isPlaying = false;
}
bool magSlideShowSource::initialize(magSlideShowSource::Settings settings)
{
this->settings = settings;
bool success = true;
if (settings.width <= 0 || settings.height <= 0)
{
ofLogError("magSlideShowSource::initialize") << "Invalid value for width or height. Width and height "
"must be assigned in your Settings struct!";
return false;
}
// Allocate the FBO:
allocate(settings.width, settings.height);
// If there is a path in slidesFolderPath, attempt
// to load the folder and any files in it:
if (!settings.slidesFolderPath.empty())
{
// ofDirectory dir = ofDirectory(settings.slidesFolderPath);
success = createFromFolderContents(settings.slidesFolderPath);
if (!success)
{
ofLogError("magSlideShowSource::initialize") << "Failed to create slide show from folder "
<< settings.slidesFolderPath;
return success;
}
}
else if (!settings.slideshowFilePath.empty())
{
// try to load slide show from xml
success = false;
}
return success;
}
void magSlideShowSource::setup()
{
ofx::piMapper::FboSource::setup();
}
void magSlideShowSource::update()
{
if (!isPlaying) return;
auto nowTime = ofGetElapsedTimeMillis();
deltaTime = nowTime-lastTime;
runningTime += deltaTime;
lastTime = nowTime;
// ofLogVerbose() << "Delta: " << deltaTime << " running: " << runningTime;
for (auto &slide : activeSlides)
{
slide->update(deltaTime);
}
// Erase any complete slides:
auto iter = activeSlides.begin();
for (; iter < activeSlides.end(); iter++)
{
if ((*iter)->isSlideComplete())
{
// ofLogVerbose() << "Removing from active slides id: " << (*iter)->getId();
activeSlides.erase(iter);
--iter;
}
}
if (activeSlides.size() == 0 && isPlaying)
{
ofEventArgs args;
isPlaying = false;
ofNotifyEvent(slideshowCompleteEvent, args, this);
}
}
void magSlideShowSource::draw()
{
ofBackground(0, 0);
ofPushMatrix();
ofPushStyle();
ofTranslate(getWidth()/2.0f, getHeight()/2.0f);
ofEnableAlphaBlending();
ofSetRectMode(OF_RECTMODE_CENTER);
ofFill();
ofSetColor(255, 255);
for (auto &slide : activeSlides)
{
slide->draw();
}
ofPopStyle();
ofPopMatrix();
ofDisableAlphaBlending();
}
bool magSlideShowSource::createFromFolderContents(std::string path)
{
ofDirectory dir = ofDirectory(path);
slides.clear();
if (!dir.isDirectory())
{
ofLogError("magSlideShowSource::createFromFolderContents") << "Folder path " << dir.getAbsolutePath()
<< " is not a directory";
return false;
}
auto sortedDir = dir.getSorted();
auto files = sortedDir.getFiles();
if (files.size() < 1)
{
ofLogError("magSlideShowSource::createFromFolderContents") << "Folder " << dir.getAbsolutePath() << " is empty";
return false;
}
ofImage tempImage;
for (auto &file : files)
{
if (tempImage.load(file))
{
// make a new image slide
auto slide = std::make_shared<magImageSlide>();
slide->setup(tempImage);
slide->setDuration(static_cast<u_int64_t>(settings.slideDuration*1000));
slide->setTransitionDuration(static_cast<u_int64_t>(settings.transitionDuration*1000));
// if (settings.transitionName == "")
addSlide(slide);
}
else
{
auto ext = ofToLower(file.getExtension());
static std::vector<std::string> movieExtensions = {
"mov", "qt", // Mac
"mp4", "m4p", "m4v", // MPEG
"mpg", "mp2", "mpeg", "mpe", "mpv", "m2v", // MPEG
"3gp", // Phones
"avi", "wmv", "asf", // Windows
"webm", "mkv", "flv", "vob", // Other containers
"ogv", "ogg",
"drc", "mxf"
};
// Check if the extension matches known movie formats:
if (ofContains(movieExtensions, ext))
{
// Make a new video slide
auto slide = std::make_shared<magVideoSlide>();
if (slide->setup(file))
{
slide->setDuration(settings.slideDuration*1000.0);
slide->setTransitionDuration(settings.transitionDuration*1000.0);
addSlide(slide);
}
else
{
ofLogError("magSlideShowSource") << "Failed loading video: " << file.getAbsolutePath();
}
}
}
}
if (slides.size() > 0)
{
return true;
}
else
{
return false;
}
}
bool magSlideShowSource::loadFromXml()
{
auto *loader = ofx::piMapper::SettingsLoader::instance();
auto xml = ofxXmlSettings();
Settings settings;
if (!xml.load(loader->getLastLoadedFilename()))
{
ofLogError("magSlideShowSource") << "Could not load settings file " << loader->getLastLoadedFilename();
return false;
}
xml.pushTag("surfaces");
if (!xml.pushTag("magSlideShow"))
{
ofLogError("magSlideShowSource") << "Slide show settings not found in " << loader->getLastLoadedFilename();
return false;
}
settings.width = xml.getValue("Width", settings.width);
settings.height = xml.getValue("Height", settings.height);
// Default slide duration:
settings.slideDuration = xml.getValue("SlideDuration", settings.slideDuration);
// Default loop:
if (xml.pushTag("Loop"))
{
auto type = xml.getValue("Type", "");
if (type == "NONE")
{
settings.loopType = LoopType::NONE;
}
else if (type == "NORMAL")
{
settings.loopType = LoopType::NORMAL;
}
else if (type == "PING-PONG")
{
settings.loopType = LoopType::PING_PONG;
}
settings.numLoops = xml.getValue("Count", settings.numLoops);
xml.popTag();
}
// Default resize options:
auto ropts = xml.getValue("ResizeOption", "");
if (ropts == "NoResize")
{
settings.resizeOption = magSlide::NoResize;
}
else if (ropts == "Native")
{
settings.resizeOption = magSlide::Native;
}
else if (ropts == "Fit")
{
settings.resizeOption = magSlide::Fit;
}
else if (ropts == "FitProportionally")
{
settings.resizeOption = magSlide::FitProportionally;
}
else if (ropts == "FillProportionally")
{
settings.resizeOption = magSlide::FillProportionally;
}
settings.transitionName = "Dissolve";
settings.transitionDuration = 0.5;
initialize(settings);
return true;
}
void magSlideShowSource::addSlide(std::shared_ptr<magSlide> slide)
{
// ofLogVerbose("addSlide") << slide->getId();
slides.insert(slides.begin(), slide);
auto rOption = slide->getResizeOption();
// If the slide does not have a resize option assign
// the slide show's option
if (rOption == magSlide::ResizeOptions::NoResize)
{
rOption = settings.resizeOption;
}
// Resize the slide according to the resize option:
switch (rOption)
{
float sw, sh, ratio;
case magSlide::ResizeOptions::FitProportionally:
sw = slide->getWidth();
sh = slide->getHeight();
if (sw > sh)
{
ratio = (float) getWidth()/sw;
}
else
{
ratio = (float) getHeight()/sh;
}
slide->setSize(sw*ratio, sh*ratio);
break;
case magSlide::ResizeOptions::FillProportionally:
sw = slide->getWidth();
sh = slide->getHeight();
if (sw > sh)
{
ratio = (float) getHeight()/sh;
}
else
{
ratio = (float) getWidth()/sw;
}
slide->setSize(sw*ratio, sh*ratio);
break;
case magSlide::Fit:
slide->setSize(getWidth(), getHeight());
break;
}
// Add transitions:
if (!settings.transitionName.empty())
{
static ofParameterGroup bogusParamGroup; // This is temporary so that things compile
auto tf = magSlideTransitionFactory::instance();
// slide->buildIn = tf->createTransition(settings.transitionName,
// slide,
// bogusParamGroup,
// slide->buildInDuration);
slide->transition = tf->createTransition(settings.transitionName,
slide,
bogusParamGroup,
slide->buildOutDuration);
}
//// void method(const void * sender, ArgumentsType &args)
ofAddListener(slide->slideStateChangedEvent, this, &magSlideShowSource::slideStateChanged);
ofAddListener(slide->slideCompleteEvent, this, &magSlideShowSource::slideComplete);
}
void magSlideShowSource::play()
{
if (!isPlaying)
{
runningTime = 0;
lastTime = ofGetElapsedTimeMillis();
isPlaying = true;
auto currentSlide = slides[currentSlideIndex];
enqueueSlide(currentSlide, ofGetElapsedTimeMillis());
}
}
void magSlideShowSource::pause()
{
isPlaying = false;
}
void magSlideShowSource::playNextSlide()
{
//TODO
// I should check here to see if there are less than two slides.
// If so, we should probably return
currentSlideIndex += direction;
ofEventArgs args;
// This makes sure that we are doing a signed integer comparison,
// otherwise things get weird
int num = slides.size();
switch (settings.loopType)
{
case LoopType::NONE:
if (currentSlideIndex >= slides.size() || currentSlideIndex < 0)
{
// If we are not looping and we are out of bounds, return
// without enqueueing a slide. This will cause the slide show
// to end once the last slide builds out.
return;
}
break;
case LoopType::NORMAL:
if (currentSlideIndex >= num)
{
loopCount++;
if (loopCount == settings.numLoops)
{
// Return without enqueueing a new slide if we have
// reached the max number of loops.
return;
}
currentSlideIndex = 0;
ofNotifyEvent(slideshowWillLoopEvent, args, this);
}
else if (currentSlideIndex < 0)
{
loopCount++;
if (loopCount == settings.numLoops)
{
// Return without enqueueing a new slide if we have
// reached the max number of loops.
return;
}
currentSlideIndex = slides.size()-1;
ofNotifyEvent(slideshowWillLoopEvent, args, this);
}
break;
case LoopType::PING_PONG:
int num = slides.size();
if (currentSlideIndex >= num)
{
loopCount++;
if (loopCount == settings.numLoops)
{
// Return without enqueueing a new slide if we have
// reached the max number of loops.
return;
}
direction = -1;
currentSlideIndex = slides.size()-2;
ofNotifyEvent(slideshowWillLoopEvent, args, this);
}
else if (currentSlideIndex < 0)
{
loopCount++;
if (loopCount == settings.numLoops)
{
// Return without enqueueing a new slide if we have
// reached the max number of loops.
return;
}
direction = 1;
currentSlideIndex = 1;
ofNotifyEvent(slideshowWillLoopEvent, args, this);
}
break;
}
enqueueSlide(slides[currentSlideIndex], ofGetElapsedTimeMillis());
}
void magSlideShowSource::playPrevSlide()
{
currentSlideIndex -= (direction*2);
playNextSlide();
}
void magSlideShowSource::playSlide(int slideIndex)
{
currentSlideIndex = slideIndex-direction;
playNextSlide();
}
void magSlideShowSource::enqueueSlide(std::shared_ptr<magSlide> slide, u_int64_t startTime)
{
// ofLogVerbose() << "Enqueuing slide " << currentSlideIndex << " slide id: " << slide->getId();
slide->start(startTime);
activeSlides.insert(activeSlides.begin(), slide);
}
void magSlideShowSource::slideStateChanged(const void *sender, ofEventArgs &args)
{
magSlide *slide = (magSlide *) sender;
// ofLogVerbose("slideStateChanged") << "Slide id: " << slide->getId() << " Slide state: "
// << slide->getSlideStateName();
if (slide->getSlideState() == magSlide::SlideState::BuildOut)
{
// slide->transition->start();
// ofLogVerbose() << "BuildOut " << slide->getId();
playNextSlide();
if (activeSlides.size() > 1)
{
activeSlides[1]->transition->start(activeSlides[0]);
}
}
}
void magSlideShowSource::slideComplete(const void *sender, ofEventArgs &args)
{
magSlide *slide = (magSlide *) sender;
// ofLogVerbose() << "Slide Complete. id: " << slide->getId();
slide->isComplete = true;
}

161
src/Sources/magSlideShowSource.h

@ -0,0 +1,161 @@
//
// magSlideShowSource.h
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#ifndef MAGSLIDESHOWSOURCE_H
#define MAGSLIDESHOWSOURCE_H
#include "FboSource.h"
#include "magSlide.h"
class magSlide;
class magSlideShowSource : public ofx::piMapper::FboSource
{
public:
magSlideShowSource();
struct Settings; // forward declaration
bool initialize(magSlideShowSource::Settings settings);
void setup() override;
void update() override;
void draw() override;
/**
* Removes all slides and then attempts to create a new slide show
* based on the contents of the ofDirectory specified. The files may
* be images or videos, which will be transformed into the appropriate slide type.
* Any other file type in the directory is ignored (including other directories).
* The slide order is alphabetical according to filename.
*
* @param dir The ofDirectory to use as a source for a slide show.
* @return true if at least one slide was created. false is returned
* otherwise. Check the console for the specific error.
*/
bool createFromFolderContents(std::string path);
bool loadFromXml();
void addSlide(std::shared_ptr<magSlide> slide);
void play();
void pause();
void playNextSlide();
void playPrevSlide();
void playSlide(int slideIndex);
enum LoopType : int
{
NONE = 0,
NORMAL,
PING_PONG
};
struct Settings
{
/**
* The pixel width of the FBO.
*/
float width = 1280;
/**
* The pixel height of the FBO.
*/
float height = 720;
/**
* An optional default slide duration, in seconds.
* If a slide specifies a duration this value is ignored.
*/
float slideDuration = 5;
/**
* An optional default transition for the slide show.
*/
std::string transitionName = "";
/**
* An optional default transition duration. If no transition
* is specified, this value is ignored;
*/
float transitionDuration = 0;
/**
* If specified, all applicable files in the folder will
* be used as slides in the slide show. They will be ordered
* alphabetically according to their file names.
*
* If path is relative, the root will likely be the Data folder.
*/
std::string slidesFolderPath = "sources/images";
/**
* If specified,
*/
std::string slideshowFilePath;
/**
* Loop type for the slide show. See @code LoopType for options.
* The default is @code LoopType:None.
*/
LoopType loopType = LoopType::NONE;
/**
* The number of loops to perform, if the loopType is not NONE.
* If the value is 0 or less than 0, the slide show loops forever.
*/
int numLoops = 0;
/**
* The resizing option for the slide show. The default is FitProportionally.
* If a slide already has a resizing option applied, that option will be
* respected and this resizeOption will not be used.
*/
magSlide::ResizeOptions resizeOption = magSlide::ResizeOptions::FitProportionally;
};
////////////////////////////////////////////
//// Event Listeners
////////////////////////////////////////////
void slideStateChanged(const void* sender, ofEventArgs &args);
void slideComplete(const void* sender, ofEventArgs &args);
/**
* Fires when the slide show is done, which happens when
* the loop count is equal to Settings::numLoops, or when
* the last slide is played when @code LoopType::NONE is specified.
* Sender is this slide show.
*/
ofEvent<ofEventArgs> slideshowCompleteEvent;
/**
* Fires when the slide show reaches the last slide
* and will perform a loop in the next call.
* Sender is this slide show.
*/
ofEvent<ofEventArgs> slideshowWillLoopEvent;
protected:
Settings settings;
std::vector<std::shared_ptr<magSlide>> slides;
private:
// std::shared_ptr<magSlide> currentSlide;
std::vector<std::shared_ptr<magSlide>> activeSlides;
void enqueueSlide(std::shared_ptr<magSlide> slide, u_int64_t startTime);
u_int64_t lastTime;
u_int64_t deltaTime;
u_int64_t runningTime;
bool isInitialized = false;
bool isPlaying = false;
int currentSlideIndex = 0;
int direction = 1;
int loopCount = 0;
};
#endif

60
src/Sources/magSlideTransition.cpp

@ -0,0 +1,60 @@
//
// magSlideTransition.cpp
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#include "magSlideTransition.h"
void magSlideTransition::start(std::shared_ptr<magSlide> nextSlide)
{
runningTime = 0;
active = true;
this->nextSlide = nextSlide;
}
void magSlideTransition::update(u_int64_t timeDelta)
{
if (!active) return;
runningTime += timeDelta;
if (runningTime >= duration)
{
ofEventArgs arghh; // arghhhh...
nextSlide->setOpacity(255);
nextSlide->setPosition(0, 0);
end();
transitionCompleteEvent.notify(this, arghh);
active = false;
}
}
u_int64_t magSlideTransition::getRunningTime()
{
return runningTime;
}
float magSlideTransition::getNormalizedTime()
{
return (double)runningTime / (double)duration;
}
void magDissolveTransition::draw()
{
slide->setOpacity(255 - (getNormalizedTime() * 255));
nextSlide->setOpacity(getNormalizedTime()*255);
}
void magDissolveTransition::start(std::shared_ptr<magSlide> nextSlide)
{
magSlideTransition::start(nextSlide);
nextSlide->setOpacity(0);
}
void magDissolveTransition::end()
{
nextSlide->setOpacity(255);
slide->setOpacity(0);
}

129
src/Sources/magSlideTransition.h

@ -0,0 +1,129 @@
//
// magSlideTransition.h
// Copyright (c) 2017 Cristobal Mendoza
// http://cuppetellimendoza.com
//
#ifndef MAGSLIDETRANSITION_H
#define MAGSLIDETRANSITION_H
#include "magSlide.h"
class magSlideTransitionFactory;
class magSlideTransition
{
public:
/**
* Subclassing notes: Make sure to provide a value for name in your
* magSlideTransition subclass.
*/
magSlideTransition() { name = "Void"; }
/**
* Begins the transition. This needs to be called in order for the
* transition to do anything.
* @param nextSlide The subsequent slide in the slide show needs to be
* passed here.
*
* You can override this call to set any initial conditions to the transition,
* but make sure to call this method in your override.
*/
virtual void start(std::shared_ptr<magSlide> nextSlide);
/**
* Called automatically when the transition is complete. Useful to set
* end states for the parameters of the slide and nextSlide. Default implementation
* does nothing.
*/
virtual void end(){}
/**
* NOTE: The transition settings system is not yet implemented.
* Called when the transition is created. Loads settings for magSlideTransition
* subclasses. The default implementation does nothing.
* @param settings ofParameterGroup with settings for your custom magSlideTransition
* subclass.
*/
virtual void loadSettings(ofParameterGroup &settings){}
/**
* Updates the transition.
* @param timeDelta The elapsed time (in ms.) between the last call to update() and
* this one (i.e. the frame time).
*
* If you need to override update, make sure to call this implementation
* in your subclass.
*/
virtual void update(u_int64_t timeDelta);
/**
* Draws the transition. Default implementation does nothing.
*/
virtual void draw(){
ofLogNotice("magSlideTransition") << "transition draw - this should be overriden " << getNormalizedTime();
}
/**
* Current running time in milliseconds.
* @return u_int64_t
*/
u_int64_t getRunningTime();
/**
* Returns the current time in normalized form.
* 0 = start, 1 = end.
* @return Float between 0 and 1.
*/
float getNormalizedTime();
string const &getName() const
{
return name;
}
const shared_ptr<magSlide> &getNextSlide() const
{
return nextSlide;
}
bool isActive() const
{
return active;
}
/**
* Sender is a raw pointer to this magSlideTransition
*/
ofEvent<ofEventArgs> transitionCompleteEvent;
protected:
std::string name;
std::shared_ptr<magSlide> slide;
std::shared_ptr<magSlide> nextSlide;
u_int64_t runningTime;
u_int64_t duration;
u_int64_t endTime;
bool active = false;
protected:
friend class magSlideTransitionFactory;
};
class magDissolveTransition : public magSlideTransition
{
public:
magDissolveTransition()
{
name = "Dissolve";
}
void start(std::shared_ptr<magSlide> nextSlide) override;
void draw() override;
void end() override;
};
#endif

76
src/Sources/magSlideTransitionFactory.cpp

@ -0,0 +1,76 @@
//
// Created by Cristobal Mendoza on 12/3/17.
//
#include "magSlideTransitionFactory.h"
/*
*
*
*
class Base {};
class DerivedA : public Base {};
class DerivedB : public Base {};
class DerivedC : public Base {};
Base* create(const std::string& type)
{
static std::map<std::string, std::function<Base*()>> type_creator_map =
{
{"DerivedA", [](){return new DerivedA();}},
{"DerivedB", [](){return new DerivedB();}},
{"DerivedC", [](){return new DerivedC();}}
};
auto it = type_creator_map.find(type);
if(it != type_creator_map.end())
{
return it->second();
}
return nullptr;
}
*/
magSlideTransitionFactory* magSlideTransitionFactory::_instance = 0;
magSlideTransitionFactory::magSlideTransitionFactory()
{
magSlideTransition voidTransition;
magDissolveTransition dissolve;
registerTransition<magSlideTransition>(voidTransition);
registerTransition<magDissolveTransition>(dissolve);
}
magSlideTransitionFactory* magSlideTransitionFactory::instance()
{
if (_instance == 0)
{
_instance = new magSlideTransitionFactory();
}
return _instance;
}
std::shared_ptr<magSlideTransition>
magSlideTransitionFactory::createTransition(std::string transitionName, std::shared_ptr<magSlide> slide,
ofParameterGroup &settings, u_int64_t duration)
{
std::shared_ptr<magSlideTransition> transition;
if (transitionsMap.count(transitionName) > 0)
{
transition = transitionsMap[transitionName]();
}
else
{
transition = transitionsMap[transition->getName()]();
}
transition->slide = slide;
transition->duration = duration;
transition->loadSettings(settings);
return transition;
}

41
src/Sources/magSlideTransitionFactory.h

@ -0,0 +1,41 @@
//
// Created by Cristobal Mendoza on 12/3/17.
//
#ifndef MAGSLIDETRANSITIONFACTORY_H
#define MAGSLIDETRANSITIONFACTORY_H
#include "magSlide.h"
#include "magSlideTransition.h"
/**
* Factory class to register and instantiate transitions.
*/
class magSlideTransitionFactory
{
public:
static magSlideTransitionFactory* instance();
std::shared_ptr<magSlideTransition> createTransition(string transitionName,
std::shared_ptr<magSlide> slide,
ofParameterGroup &group,
u_int64_t duration);
template<typename T>
void registerTransition(T transition)
{
if (transitionsMap.count(transition.getName()) == 0)
{
transitionsMap[transition.getName()] = [](){
return std::make_shared<T>();
};
}
}
protected:
std::unordered_map<std::string, std::function<std::shared_ptr<magSlideTransition>()>> transitionsMap;
private:
static magSlideTransitionFactory* _instance;
magSlideTransitionFactory();
};
#endif //MAGSLIDETRANSITIONFACTORY_H

4
src/ofxPiMapper.cpp

@ -166,6 +166,10 @@ void ofxPiMapper::setNextSource(){
_application.setNextSource(); _application.setNextSource();
} }
void ofxPiMapper::setFboSource(string sourceId){
_application.setFboSource(sourceId);
}
void ofxPiMapper::reboot(){ void ofxPiMapper::reboot(){
_application.reboot(); _application.reboot();
} }

21
src/ofxPiMapper.h

@ -14,31 +14,31 @@ class ofxPiMapper {
void setup(); void setup();
void update(); void update();
void draw(); void draw();
void keyPressed(int key); void keyPressed(int key);
void keyReleased(int key); void keyReleased(int key);
void mousePressed(int x, int y, int button); void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button); void mouseReleased(int x, int y, int button);
void mouseDragged(int x, int y, int button); void mouseDragged(int x, int y, int button);
void registerFboSource(ofx::piMapper::FboSource & fboSource); void registerFboSource(ofx::piMapper::FboSource & fboSource);
void registerFboSource(ofx::piMapper::FboSource * fboSource); void registerFboSource(ofx::piMapper::FboSource * fboSource);
// Application // Application
void setInfoText(string text); void setInfoText(string text);
void toggleInfo(); void toggleInfo();
void undo(); void undo();
void deselect(); void deselect();
// Modes // Modes
void setMode(ofx::piMapper::Mode m); void setMode(ofx::piMapper::Mode m);
ofx::piMapper::Mode getMode(); ofx::piMapper::Mode getMode();
// Project // Project
void saveProject(); void saveProject();
bool loadProject(string filename); bool loadProject(string filename);
// Presets // Presets
unsigned int getNumPresets(); unsigned int getNumPresets();
unsigned int getActivePresetIndex(); unsigned int getActivePresetIndex();
@ -46,7 +46,7 @@ class ofxPiMapper {
void setNextPreset(); void setNextPreset();
void cloneActivePreset(); void cloneActivePreset();
void eraseActivePreset(); void eraseActivePreset();
// Surfaces, active preset // Surfaces, active preset
unsigned int getNumSurfaces(); unsigned int getNumSurfaces();
int getSelectedSurface(); int getSelectedSurface();
@ -69,10 +69,11 @@ class ofxPiMapper {
void moveSelection(ofVec2f by); void moveSelection(ofVec2f by);
void createSurface(ofx::piMapper::SurfaceType type); void createSurface(ofx::piMapper::SurfaceType type);
void eraseSurface(int i); void eraseSurface(int i);
// Sources, selected surface // Sources, selected surface
void setNextSource(); void setNextSource();
void setFboSource(string sourceId);
// System commands // System commands
void reboot(); void reboot();
void shutdown(); void shutdown();

Loading…
Cancel
Save