23 changed files with 2292 additions and 966 deletions
File diff suppressed because it is too large
@ -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; |
||||
|
} |
||||
|
|
@ -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 |
@ -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; |
||||
|
} |
||||
|
|
||||
|
|
@ -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 |
@ -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); |
||||
|
} |
@ -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 |
@ -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; |
||||
|
} |
@ -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
|
Loading…
Reference in new issue