Skip to content

Commit 572a1ac

Browse files
authored
Merge pull request #22 from mitmedialab/smoothTransition
Smooth transition
2 parents 8f0e93a + c283aef commit 572a1ac

File tree

5 files changed

+168
-2
lines changed

5 files changed

+168
-2
lines changed

neoForm.xcodeproj/project.pbxproj

+6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
B266578FC55D23BFEBC042E7 /* ofxGuiGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECF8674C7975F1063C5E30CA /* ofxGuiGroup.cpp */; };
7878
B56FE57CC35806596D38118C /* ofxSliderGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 802251BAF1B35B1D67B32FD0 /* ofxSliderGroup.cpp */; };
7979
B917C91A2D0F882700F26C4C /* AmbientWave.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B917C9182D0F882700F26C4C /* AmbientWave.cpp */; };
80+
B917C91D2D0F8E3400F26C4C /* TransitionApp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B917C91B2D0F8E3300F26C4C /* TransitionApp.cpp */; };
8081
B951ED692CEA6F6E00C74190 /* WaveModeContours.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B951ED652CEA6F6E00C74190 /* WaveModeContours.cpp */; };
8182
B951ED6E2CEA703B00C74190 /* EquationMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B951ED6C2CEA703B00C74190 /* EquationMode.cpp */; };
8283
BBC747EFA455E446D3C6C588 /* AppManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB71C7D49B032CA4888457E3 /* AppManager.cpp */; };
@@ -573,6 +574,8 @@
573574
B8F39F6EBA0607ECB7D18D89 /* handle_disconnect.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 4; name = handle_disconnect.c; path = "../../../addons/ofxMQTT-1.5.0/libs/mosquitto/src/handle_disconnect.c"; sourceTree = SOURCE_ROOT; };
574575
B917C9182D0F882700F26C4C /* AmbientWave.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AmbientWave.cpp; path = Applications/AmbientWave.cpp; sourceTree = "<group>"; };
575576
B917C9192D0F882700F26C4C /* AmbientWave.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = AmbientWave.hpp; path = Applications/AmbientWave.hpp; sourceTree = "<group>"; };
577+
B917C91B2D0F8E3300F26C4C /* TransitionApp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TransitionApp.cpp; path = Applications/TransitionApp.cpp; sourceTree = "<group>"; };
578+
B917C91C2D0F8E3300F26C4C /* TransitionApp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = TransitionApp.hpp; path = Applications/TransitionApp.hpp; sourceTree = "<group>"; };
576579
B91E6F7343623AFE1F02BF84 /* SerialShapeIO.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SerialShapeIO.hpp; path = src/ShapeDisplayManagers/SerialShapeIO.hpp; sourceTree = SOURCE_ROOT; };
577580
B951ED652CEA6F6E00C74190 /* WaveModeContours.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WaveModeContours.cpp; path = Applications/WaveModeContours.cpp; sourceTree = "<group>"; };
578581
B951ED662CEA6F6E00C74190 /* WaveModeContours.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = WaveModeContours.hpp; path = Applications/WaveModeContours.hpp; sourceTree = "<group>"; };
@@ -2525,6 +2528,8 @@
25252528
E4B69E1F0A3A1BDC003C02F2 /* ofApp.h */,
25262529
3EE80DAFB34047B8B800B342 /* AppManager.hpp */,
25272530
FB71C7D49B032CA4888457E3 /* AppManager.cpp */,
2531+
B917C91B2D0F8E3300F26C4C /* TransitionApp.cpp */,
2532+
B917C91C2D0F8E3300F26C4C /* TransitionApp.hpp */,
25282533
4997C055D8B8304C523D6B00 /* DisplayApp.hpp */,
25292534
56B0CE0DEBBD93163AF7C1A2 /* DisplayApp.cpp */,
25302535
BDDCA57B66B030A4C45FF4D6 /* ProjectorApp.hpp */,
@@ -2906,6 +2911,7 @@
29062911
661A1991F5CE4CCC2919D8E7 /* ofxNetworkUtils.cpp in Sources */,
29072912
960D20B191346612D5C05A6A /* ofxTCPClient.cpp in Sources */,
29082913
125506CD3E5F428AAFE5CC65 /* ofxTCPManager.cpp in Sources */,
2914+
B917C91D2D0F8E3400F26C4C /* TransitionApp.cpp in Sources */,
29092915
66CA411C5A9664E27326BF36 /* ofxTCPServer.cpp in Sources */,
29102916
E2564CF7DDB3713772BB682E /* ofxUDPManager.cpp in Sources */,
29112917
250A95BA26587BE85DB0A353 /* ofxCvColorImage.cpp in Sources */,

src/AppManager.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "AppManager.hpp"
99
#include "AmbientWave.hpp"
1010
#include "SinglePinDebug.hpp"
11+
#include "TransitionApp.hpp"
1112
#include "ofEvents.h"
1213
#include "ofGraphics.h"
1314
#include "utils.hpp"
@@ -63,6 +64,9 @@ void AppManager::setup() {
6364

6465
waveModeContours = new WaveModeContours(m_serialShapeIOManager, kinectManager);
6566
applications["waveModeContours"] = waveModeContours;
67+
68+
// not in applications list
69+
transitionApp = new TransitionApp(m_serialShapeIOManager);
6670

6771
ambientWave = new AmbientWave(m_serialShapeIOManager);
6872
applications["AmbientWave"] = ambientWave;
@@ -297,11 +301,20 @@ void AppManager::draw() {
297301
}
298302

299303
void AppManager::setCurrentApplication(string appName) {
304+
if (applicationSwitchBlocked) return;
305+
300306
if (applications.find(appName) == applications.end()) {
301307
throw "no application exists with name " + appName;
302308
}
309+
310+
if (currentApplication == nullptr) {
311+
currentApplication = applications[appName];
312+
} else {
313+
applicationSwitchBlocked = true;
314+
transitionApp->startTransition(currentApplication, applications[appName], 0.6f, &currentApplication, &applicationSwitchBlocked);
315+
currentApplication = transitionApp;
316+
}
303317

304-
currentApplication = applications[appName];
305318
updateDepthInputBoundaries();
306319
}
307320

src/AppManager.hpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@
4848

4949
#include "WaveModeContours.hpp"
5050

51+
#include "TransitionApp.hpp"
52+
5153
#include "AmbientWave.hpp"
5254

5355

56+
5457
class AppManager : public ofBaseApp {
5558

5659
public:
@@ -116,7 +119,12 @@ class AppManager : public ofBaseApp {
116119

117120
WaveModeContours *waveModeContours;
118121

119-
AmbientWave *ambientWave;
122+
TransitionApp *transitionApp;
123+
bool applicationSwitchBlocked = false;
124+
125+
126+
AmbientWave *ambientWave;
127+
120128

121129
// program state
122130
bool paused = false;

src/Applications/TransitionApp.cpp

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//
2+
// TransitionApp.cpp
3+
// neoForm
4+
//
5+
// Created by Charles Reischer 12/14/24.
6+
//{
7+
8+
#include "TransitionApp.hpp"
9+
#include "ofGraphics.h"
10+
#include <sstream>
11+
12+
std::string TransitionApp::getName() {
13+
if (startApp == nullptr || endApp == nullptr) return "Interpolate";
14+
std::stringstream name = std::stringstream("Interpolate (");
15+
name << startApp->getName() << " -> " << endApp->getName() << ")";
16+
return name.str();
17+
}
18+
19+
void TransitionApp::startTransition(Application* start, Application* end, float duration, Application** pointerToActiveApplication, bool* pointerToBlock) {
20+
startApp = start;
21+
endApp = end;
22+
transitionDuration = duration;
23+
transitionProgress = 0.0f;
24+
appManagerPointer = pointerToActiveApplication;
25+
appManagerBlock = pointerToBlock;
26+
}
27+
28+
void TransitionApp::update(float dt) {
29+
if (startApp == nullptr || endApp == nullptr || appManagerPointer == nullptr) {
30+
std::cout << "breaking (nullptr)" << std::endl;
31+
return;
32+
}
33+
transitionProgress += dt;
34+
35+
if (transitionProgress >= transitionDuration) {
36+
// manually sets the appManager's active app
37+
*appManagerPointer = endApp;
38+
*appManagerBlock = false;
39+
endApp->update(dt);
40+
return;
41+
}
42+
43+
startApp->update(dt);
44+
endApp->update(dt);
45+
46+
// blend heights from startApp and endApp
47+
startApp->getHeightsForShapeDisplay(heightsForShapeDisplay);
48+
ofPixels endHeights;
49+
endApp->getHeightsForShapeDisplay(endHeights);
50+
51+
for (int i = 0; i < heightsForShapeDisplay.size(); i++) {
52+
float l = transitionProgress/transitionDuration;
53+
heightsForShapeDisplay[i] = (1.0f - l) * heightsForShapeDisplay[i] + l * endHeights[i];
54+
}
55+
}
56+
57+
void fade(int x, int y, int width, int height, double alpha) {
58+
ofSetColor(0, 0, 0, alpha);
59+
ofDrawRectangle(x, y, width, height);
60+
ofSetColor(255);
61+
}
62+
63+
void TransitionApp::drawGraphicsForShapeDisplay(int x, int y, int width, int height) {
64+
if (startApp == nullptr || endApp == nullptr) return;
65+
if (transitionProgress <= transitionDuration/2.0f) {
66+
startApp->drawGraphicsForShapeDisplay(x, y, width, height);
67+
fade(x, y, width, height, 255.0f * 2.0f * transitionProgress / transitionDuration);
68+
} else {
69+
endApp->drawGraphicsForShapeDisplay(x, y, width, height);
70+
fade(x, y, width , height, 255.0 * 2.0f * (transitionDuration - transitionProgress) / transitionDuration);
71+
}
72+
}
73+
74+
void TransitionApp::drawGraphicsForPublicDisplay(int x, int y, int width, int height) {
75+
if (startApp == nullptr || endApp == nullptr) return;
76+
if (transitionProgress <= transitionDuration/2.0f) {
77+
startApp->drawGraphicsForPublicDisplay(x, y, width, height);
78+
fade(x, y, width, height, 255.0f * 2.0f * transitionProgress / transitionDuration);
79+
} else {
80+
endApp->drawGraphicsForPublicDisplay(x, y, width, height);
81+
fade(x, y, width , height, 255.0 * 2.0f * (transitionDuration - transitionProgress) / transitionDuration);
82+
}
83+
}
84+
85+
void TransitionApp::drawGraphicsForProjector(int x, int y, int width, int height) {
86+
if (startApp == nullptr || endApp == nullptr) return;
87+
if (transitionProgress <= transitionDuration/2.0f) {
88+
startApp->drawGraphicsForProjector(x, y, width, height);
89+
fade(x, y, width, height, 255.0f * 2.0f * transitionProgress / transitionDuration);
90+
} else {
91+
endApp->drawGraphicsForProjector(x, y, width, height);
92+
fade(x, y, width , height, 255.0 * 2.0f * (transitionDuration - transitionProgress) / transitionDuration);
93+
}
94+
}
95+
96+
void TransitionApp::keyPressed(int key) {
97+
if (startApp == nullptr || endApp == nullptr) return;
98+
startApp->keyPressed(key);
99+
endApp->keyPressed(key);
100+
}

src/Applications/TransitionApp.hpp

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// TransitionApp.hpp
3+
// neoForm
4+
//
5+
// Created by Charles Reischer 12/14/24.
6+
//
7+
8+
#ifndef TransitionApp_hpp
9+
#define TransitionApp_hpp
10+
11+
#include "Application.hpp"
12+
#include "SerialShapeIOManager.hpp"
13+
class TransitionApp : public Application {
14+
public:
15+
TransitionApp(SerialShapeIOManager *theCustomShapeDisplayManager) : Application(theCustomShapeDisplayManager) {}
16+
17+
std::string getName();
18+
void startTransition(Application* start, Application* end, float duration, Application** pointerToActiveApplication, bool* pointerToBlock);
19+
void update(float dt);
20+
void drawGraphicsForShapeDisplay(int x, int y, int width, int height);
21+
void drawGraphicsForPublicDisplay(int x, int y, int width, int height);
22+
void drawGraphicsForProjector(int x, int y, int width, int height);
23+
void keyPressed(int key);
24+
public:
25+
Application* startApp = nullptr;
26+
Application* endApp = nullptr;
27+
Application** appManagerPointer = nullptr;
28+
bool* appManagerBlock = nullptr;
29+
float transitionDuration = 0.0f;
30+
float transitionProgress = 0.0f;
31+
};
32+
33+
34+
35+
36+
37+
38+
39+
#endif //TransitionApp_hpp

0 commit comments

Comments
 (0)