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

3
example/addons.make

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

30
example/bin/data/ofxpimapper.xml

@ -2,16 +2,16 @@
<surface type="0">
<vertices>
<vertex>
<x>250.000000000</x>
<y>138.187255859</y>
<x>244.000000000</x>
<y>151.187255859</y>
</vertex>
<vertex>
<x>403.625549316</x>
<y>291.812774658</y>
<x>397.625549316</x>
<y>304.812774658</y>
</vertex>
<vertex>
<x>96.374511719</x>
<y>291.812774658</y>
<x>90.374511719</x>
<y>304.812774658</y>
</vertex>
</vertices>
<texCoords>
@ -36,20 +36,20 @@
<surface type="1">
<vertices>
<vertex>
<x>425.565002441</x>
<y>144.782531738</y>
<x>305.332824707</x>
<y>158.923416138</y>
</vertex>
<vertex>
<x>718.434936523</x>
<y>144.782531738</y>
<x>823.889770508</x>
<y>135.275909424</y>
</vertex>
<vertex>
<x>718.434936523</x>
<y>291.217407227</y>
<x>883.853393555</x>
<y>670.724243164</y>
</vertex>
<vertex>
<x>425.565002441</x>
<y>291.217407227</y>
<x>241.146575928</x>
<y>656.366699219</y>
</vertex>
</vertices>
<texCoords>
@ -72,7 +72,7 @@
</texCoords>
<source>
<source-type>fbo</source-type>
<source-name>Custom FBO Source</source-name>
<source-name>Slide Show Source</source-name>
</source>
<properties>
<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"?>
<Scheme
LastUpgradeVersion = "0720"
LastUpgradeVersion = "0600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
@ -38,21 +38,17 @@
ReferencedContainer = "container:example.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2"
@ -65,13 +61,12 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Debug"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E4B69B5A0A3A1756003C02F2"

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

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

4
example/openFrameworks-Info.plist

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

2
example/src/main.cpp

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

25
example/src/ofApp.cpp

@ -14,15 +14,38 @@ void ofApp::setup(){
// a surface in XML settings.
crossSource = new CrossSource();
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(customSource);
piMapper.registerFboSource(slideShowSource);
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
// piMapper.showInfo();
ofSetFullscreen(Settings::instance()->getFullscreen());
ofSetEscapeQuitsApp(false);
ofSetLogLevel(OF_LOG_VERBOSE);
slideShowSource->play();
}
void ofApp::update(){

38
example/src/ofApp.h

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

35
src/Application/Application.h

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

21
src/ofxPiMapper.h

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

Loading…
Cancel
Save