diff --git a/example/src/magSlide.cpp b/example/src/magSlide.cpp new file mode 100644 index 0000000..7e38228 --- /dev/null +++ b/example/src/magSlide.cpp @@ -0,0 +1,201 @@ +// +// 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) +{ + runningTime += deltaTime; + + switch (slideState) + { + case SlideState::BuildIn: + if (runningTime >= buildInDuration) + { + setState(Normal); + activeTransition = nullptr; + } + break; + + case SlideState::Normal: + if (runningTime >= buildOutStartTime) + { + setState(BuildOut); + if (buildOut != nullptr) + { + activeTransition = buildOut; + activeTransition->start(); + } + } + break; + + case SlideState::BuildOut: + if (runningTime >= endTime) + { + setState(Complete); + activeTransition = nullptr; + } + 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) +{ + buildInDuration = 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 + buildInDuration + buildOutDuration; + buildOutStartTime = endTime - buildOutDuration; + slideState = magSlide::SlideState::BuildIn; + if (buildIn != nullptr) + { + activeTransition = buildIn; + activeTransition->start(); + } + isComplete = false; +} + + +//////////////////////////////////////////////////////// +#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() +{ + 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() +{ + videoPlayer.draw(position.x, position.y, width, height); +} + +void magVideoSlide::useVideoForDuration() +{ + duration = u_int64_t((videoPlayer.getDuration()*1000)) - buildInDuration - buildOutDuration; +} + diff --git a/example/src/magSlide.h b/example/src/magSlide.h new file mode 100644 index 0000000..bff6d27 --- /dev/null +++ b/example/src/magSlide.h @@ -0,0 +1,227 @@ +// +// 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() = 0; + + /** + * 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. + */ + None = 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. + */ + NoResize, + + /** + * 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. + * This is the default behavior. + */ + 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; } + + /** + * 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 slideCompleteEvent; + ofEvent slideStateChangedEvent; + + friend class magSlideShowSource; + +protected: + int id; + std::string type; + float width; + float height; + ofPoint position; + ResizeOptions resizeOption = None; + SlideState slideState = Off; + bool isComplete; + + std::shared_ptr buildIn = nullptr; + std::shared_ptr buildOut = nullptr; + std::shared_ptr activeTransition = nullptr; + /** + * 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 diff --git a/example/src/magSlideShowSource.cpp b/example/src/magSlideShowSource.cpp new file mode 100644 index 0000000..a417da4 --- /dev/null +++ b/example/src/magSlideShowSource.cpp @@ -0,0 +1,415 @@ +// +// magSlideShowSource.cpp +// Copyright (c) 2017 Cristobal Mendoza +// http://cuppetellimendoza.com +// + + +#include "magSlideShowSource.h" +#include "magSlide.h" +#include "magSlideTransition.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(); + ofTranslate(getWidth()/2.0f, getHeight()/2.0f); + ofSetRectMode(OF_RECTMODE_CENTER); + for (auto &slide : activeSlides) + { + ofSetColor(255); + ofFill(); + slide->draw(); + } + ofPopMatrix(); +} + +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(); + slide->setup(tempImage); + slide->setDuration(static_cast(settings.slideDuration*1000)); + slide->setTransitionDuration(static_cast(settings.transitionDuration*1000)); +// if (settings.transitionName == "") + addSlide(slide); + } + else + { + auto ext = ofToLower(file.getExtension()); + + static std::vector 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(); + 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::loadSlideShow(std::string slideShowXmlPath) +{ + return false; +} + +void magSlideShowSource::addSlide(std::shared_ptr slide) +{ +// ofLogVerbose("addSlide") << slide->getId(); + slides.push_back(slide); + auto rOption = slide->getResizeOption(); + + // If the slide does not have a resize option assign + // the slide show's option + if (rOption == magSlide::ResizeOptions::None) + { + 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 + slide->buildIn = magSlideTransition::createTransition(settings.transitionName, + slide, + bogusParamGroup, + slide->buildInDuration); + slide->buildOut = magSlideTransition::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 slide, u_int64_t startTime) +{ +// ofLogVerbose() << "Enqueuing slide " << currentSlideIndex << " slide id: " << slide->getId(); + slide->start(startTime); + activeSlides.push_back(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) + { + playNextSlide(); + } + +} + +void magSlideShowSource::slideComplete(const void *sender, ofEventArgs &args) +{ + magSlide *slide = (magSlide *) sender; +// ofLogVerbose() << "Slide Complete. id: " << slide->getId(); + slide->isComplete = true; +} + + diff --git a/example/src/magSlideShowSource.h b/example/src/magSlideShowSource.h new file mode 100644 index 0000000..1e808ef --- /dev/null +++ b/example/src/magSlideShowSource.h @@ -0,0 +1,160 @@ +// +// 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 loadSlideShow(std::string slideShowXmlPath); + void addSlide(std::shared_ptr slide); + void play(); + void pause(); + void playNextSlide(); + void playPrevSlide(); + void playSlide(int slideIndex); + + enum LoopType + { + NONE = 0, + NORMAL, + PING_PONG + }; + + struct Settings + { + /** + * The pixel width of the FBO. This value must be provided. + */ + float width = 0; + + /** + * The pixel height of the FBO. This value must be provided. + */ + float height = 0; + /** + * 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 = 1; + + /** + * 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; + + /** + * 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 None. 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::None; + }; + + //////////////////////////////////////////// + //// 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 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 slideshowWillLoopEvent; + +protected: + Settings settings; + std::vector> slides; + +private: +// std::shared_ptr currentSlide; + std::vector> activeSlides; + void enqueueSlide(std::shared_ptr 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 diff --git a/example/src/magSlideTransition.cpp b/example/src/magSlideTransition.cpp new file mode 100644 index 0000000..54ff0c8 --- /dev/null +++ b/example/src/magSlideTransition.cpp @@ -0,0 +1,60 @@ +// +// magSlideTransition.cpp +// Copyright (c) 2017 Cristobal Mendoza +// http://cuppetellimendoza.com +// + +#include "magSlideTransition.h" + +std::shared_ptr +magSlideTransition::createTransition(std::string transitionName, std::shared_ptr slide, + ofParameterGroup &settings, u_int64_t duration) +{ + auto transition = magSlideTransition::instantiateTransition(transitionName); + transition->slide = slide; + transition->duration = duration; + transition->loadSettings(settings); + return transition; +} + +void magSlideTransition::start() +{ + runningTime = 0; + isActive = true; +} + +void magSlideTransition::update(u_int64_t timeDelta) +{ + if (!isActive) return; + + runningTime += timeDelta; + if (runningTime >= duration) + { + ofEventArgs arghh; // arghhhh... + transitionCompleteEvent.notify(this, arghh); + isActive = false; + } + +} + +u_int64_t magSlideTransition::getRunningTime() +{ + return runningTime; +} + +float magSlideTransition::getNormalizedTime() +{ + return (double)runningTime / (double)duration; +} + +std::shared_ptr magSlideTransition::instantiateTransition(string transitionName) +{ + return std::make_shared(); +} + +//magDissolveTransition::magDissolveTransition() +//{} +void magVoidTransition::loadSettings(ofParameterGroup &settings) +{ + ofLogNotice("magVoidTransition") << "Void Transition is loading nothing"; +} diff --git a/example/src/magSlideTransition.h b/example/src/magSlideTransition.h new file mode 100644 index 0000000..2c2a15d --- /dev/null +++ b/example/src/magSlideTransition.h @@ -0,0 +1,67 @@ +// +// magSlideTransition.h +// Copyright (c) 2017 Cristobal Mendoza +// http://cuppetellimendoza.com +// + +#ifndef MAGSLIDETRANSITION_H +#define MAGSLIDETRANSITION_H + + +#include "magSlide.h" + +class magSlideTransition +{ +public: + static std::shared_ptr createTransition(string transitionName, + shared_ptr ptr, + ofParameterGroup &group, + u_int64_t i); + /** + * Begins the transition. This must be called in order for the + * transition to actually do anything! + */ + void start(); + virtual void loadSettings(ofParameterGroup &settings) = 0; + virtual void setup(){} + virtual void update(u_int64_t timeDelta); + virtual void draw(){} + + /** + * 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(); + + ofEvent transitionCompleteEvent; + +protected: + magSlideTransition(){} + std::shared_ptr slide; + u_int64_t runningTime; + u_int64_t duration; + u_int64_t endTime; + bool isActive = false; + static shared_ptr instantiateTransition(string transitionName); +}; + +class magVoidTransition : public magSlideTransition +{ +public: + void loadSettings(ofParameterGroup &settings) override; +}; + +class magDissolveTransition : public magSlideTransition +{ +public: + +}; + +#endif diff --git a/example/src/main.cpp b/example/src/main.cpp index e5733f9..d743ec0 100644 --- a/example/src/main.cpp +++ b/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()); } diff --git a/example/src/ofApp.cpp b/example/src/ofApp.cpp index 93a0d08..9c75f7b 100644 --- a/example/src/ofApp.cpp +++ b/example/src/ofApp.cpp @@ -14,8 +14,27 @@ 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. + magSlideShowSource::Settings settings; + settings.width = 1280; + settings.height = 720; + settings.slidesFolderPath = "sources/images"; + settings.transitionDuration = 0; + settings.slideDuration = 0.5; + settings.loopType = magSlideShowSource::LoopType::NORMAL; + settings.resizeOption = magSlide::ResizeOptions::FitProportionally; + + // Initialize the slide show with our settings. + slideShowSource->initialize(settings); + + // Register our sources: piMapper.registerFboSource(crossSource); piMapper.registerFboSource(customSource); + piMapper.registerFboSource(slideShowSource); piMapper.setup(); // The info layer is hidden by default, press to toggle @@ -23,6 +42,9 @@ void ofApp::setup(){ ofSetFullscreen(Settings::instance()->getFullscreen()); ofSetEscapeQuitsApp(false); + ofSetLogLevel(OF_LOG_VERBOSE); + + slideShowSource->play(); } void ofApp::update(){ diff --git a/example/src/ofApp.h b/example/src/ofApp.h index 8ca4b64..5718af7 100644 --- a/example/src/ofApp.h +++ b/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; };