├── Makefile ├── resources ├── Icon.png ├── Icon@2x.png ├── glows │ ├── rings.png │ ├── star.png │ ├── atmosphere.png │ ├── lensFlare.png │ ├── particle.png │ ├── starGlow.png │ ├── eclipseGlow.png │ ├── atmosphereSun.png │ └── atmosphereDirectional.png ├── ui │ ├── dotted.png │ ├── origin.png │ ├── noArtists.png │ ├── uiButtons.png │ ├── gradientLarge.png │ ├── orbitRingGradient.png │ └── playheadProgress.png ├── misc │ ├── noAlbumArt.png │ ├── skydomeFull.png │ ├── eclipseShadow.png │ ├── galaxyCropped.jpg │ ├── darkMatterFull.png │ └── lightMatterFull.jpg ├── clouds │ ├── moonClouds1.png │ ├── moonClouds2.png │ ├── moonClouds3.png │ ├── moonClouds4.png │ ├── moonClouds5.png │ ├── planetClouds1.png │ ├── planetClouds2.png │ ├── planetClouds3.png │ ├── planetClouds4.png │ └── planetClouds5.png ├── loadscreen │ ├── planet.png │ ├── background.jpg │ └── planetary.png ├── surfaces │ ├── starCore.png │ ├── surfacesLowRes.png │ └── surfacesHighRes.png └── fonts │ ├── AauxPro-Black.ttf │ ├── UnitRoundedOT-Medi.otf │ └── UnitRoundedOT-Ultra.otf ├── .gitignore ├── xcode ├── Kepler_Prefix.pch ├── fixproject.sh └── Kepler-Info.plist ├── src ├── TextureRect.cpp ├── StringHelpers.h ├── Dust.h ├── Shadow.h ├── OrbitRing.h ├── GyroHelper.h ├── Filter.h ├── LetterFilter.h ├── PlanetRing.h ├── Stars.h ├── Device.h ├── PlaylistFilter.h ├── Particle.h ├── StarGlows.h ├── TextureRect.h ├── Stats.h ├── Dust.cpp ├── BloomSphere.h ├── Constellation.h ├── StringHelpers.mm ├── PlaylistFilter.cpp ├── TextLabel.cpp ├── TextLabel.h ├── Data.h ├── NotificationOverlay.h ├── TimeLabel.h ├── LoadingScreen.h ├── Vignette.h ├── ParticleController.h ├── NodeArtist.h ├── Particle.cpp ├── LetterFilter.cpp ├── PlanetRing.cpp ├── ScrollingLabel.h ├── Stats.cpp ├── GyroHelper.cpp ├── BloomGl.h ├── Globals.h ├── HelpLayer.h ├── Slider.h ├── AlphaChooser.h ├── TextureLoader.h ├── Galaxy.h ├── NodeAlbum.h ├── TimeLabel.cpp ├── Buttons.cpp ├── Slider.cpp ├── Constellation.cpp ├── Data.cpp ├── OrbitRing.cpp ├── PlaylistChooser.h ├── UiLayer.h ├── State.h ├── ScrollingLabel.cpp ├── State.cpp ├── NodeTrack.h ├── Vignette.cpp ├── World.h ├── Stars.cpp ├── StarGlows.cpp ├── TextureLoader.cpp ├── SettingsPanel.h ├── NotificationOverlay.cpp ├── PlayControls.h ├── BloomSphere.cpp ├── AlphaChooser.cpp ├── Buttons.h ├── ParticleController.cpp ├── LoadingScreen.cpp ├── Node.h ├── HelpLayer.cpp ├── SettingsPanel.cpp └── UiLayer.cpp ├── blocks └── BloomTasks │ └── src │ ├── TaskQueue.cpp │ └── TaskQueue.h ├── .gitmodules ├── README.md ├── bin └── src2pdf.sh └── LICENSE /Makefile: -------------------------------------------------------------------------------- 1 | pdf: 2 | ./bin/src2pdf.sh 3 | -------------------------------------------------------------------------------- /resources/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/Icon.png -------------------------------------------------------------------------------- /resources/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/Icon@2x.png -------------------------------------------------------------------------------- /resources/glows/rings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/rings.png -------------------------------------------------------------------------------- /resources/glows/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/star.png -------------------------------------------------------------------------------- /resources/ui/dotted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/ui/dotted.png -------------------------------------------------------------------------------- /resources/ui/origin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/ui/origin.png -------------------------------------------------------------------------------- /resources/ui/noArtists.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/ui/noArtists.png -------------------------------------------------------------------------------- /resources/ui/uiButtons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/ui/uiButtons.png -------------------------------------------------------------------------------- /resources/glows/atmosphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/atmosphere.png -------------------------------------------------------------------------------- /resources/glows/lensFlare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/lensFlare.png -------------------------------------------------------------------------------- /resources/glows/particle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/particle.png -------------------------------------------------------------------------------- /resources/glows/starGlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/starGlow.png -------------------------------------------------------------------------------- /resources/misc/noAlbumArt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/misc/noAlbumArt.png -------------------------------------------------------------------------------- /resources/misc/skydomeFull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/misc/skydomeFull.png -------------------------------------------------------------------------------- /resources/ui/gradientLarge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/ui/gradientLarge.png -------------------------------------------------------------------------------- /resources/clouds/moonClouds1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/moonClouds1.png -------------------------------------------------------------------------------- /resources/clouds/moonClouds2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/moonClouds2.png -------------------------------------------------------------------------------- /resources/clouds/moonClouds3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/moonClouds3.png -------------------------------------------------------------------------------- /resources/clouds/moonClouds4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/moonClouds4.png -------------------------------------------------------------------------------- /resources/clouds/moonClouds5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/moonClouds5.png -------------------------------------------------------------------------------- /resources/glows/eclipseGlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/eclipseGlow.png -------------------------------------------------------------------------------- /resources/loadscreen/planet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/loadscreen/planet.png -------------------------------------------------------------------------------- /resources/misc/eclipseShadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/misc/eclipseShadow.png -------------------------------------------------------------------------------- /resources/misc/galaxyCropped.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/misc/galaxyCropped.jpg -------------------------------------------------------------------------------- /resources/surfaces/starCore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/surfaces/starCore.png -------------------------------------------------------------------------------- /resources/clouds/planetClouds1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/planetClouds1.png -------------------------------------------------------------------------------- /resources/clouds/planetClouds2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/planetClouds2.png -------------------------------------------------------------------------------- /resources/clouds/planetClouds3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/planetClouds3.png -------------------------------------------------------------------------------- /resources/clouds/planetClouds4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/planetClouds4.png -------------------------------------------------------------------------------- /resources/clouds/planetClouds5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/clouds/planetClouds5.png -------------------------------------------------------------------------------- /resources/fonts/AauxPro-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/fonts/AauxPro-Black.ttf -------------------------------------------------------------------------------- /resources/glows/atmosphereSun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/atmosphereSun.png -------------------------------------------------------------------------------- /resources/loadscreen/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/loadscreen/background.jpg -------------------------------------------------------------------------------- /resources/loadscreen/planetary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/loadscreen/planetary.png -------------------------------------------------------------------------------- /resources/misc/darkMatterFull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/misc/darkMatterFull.png -------------------------------------------------------------------------------- /resources/misc/lightMatterFull.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/misc/lightMatterFull.jpg -------------------------------------------------------------------------------- /resources/ui/orbitRingGradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/ui/orbitRingGradient.png -------------------------------------------------------------------------------- /resources/ui/playheadProgress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/ui/playheadProgress.png -------------------------------------------------------------------------------- /resources/surfaces/surfacesLowRes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/surfaces/surfacesLowRes.png -------------------------------------------------------------------------------- /resources/fonts/UnitRoundedOT-Medi.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/fonts/UnitRoundedOT-Medi.otf -------------------------------------------------------------------------------- /resources/fonts/UnitRoundedOT-Ultra.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/fonts/UnitRoundedOT-Ultra.otf -------------------------------------------------------------------------------- /resources/surfaces/surfacesHighRes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/surfaces/surfacesHighRes.png -------------------------------------------------------------------------------- /resources/glows/atmosphereDirectional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cooperhewitt/Planetary/HEAD/resources/glows/atmosphereDirectional.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X cruft 2 | *.xcworkspace 3 | *xcuserdata 4 | *.perspectivev3 5 | *.pbxuser 6 | *.mode1v3 7 | *.mode2v3 8 | *.user 9 | .DS_Store 10 | 11 | build 12 | 13 | # Windows cruft 14 | *.suo 15 | *.ncb 16 | *.sdf 17 | Debug/ 18 | Release/ 19 | 20 | # Python 21 | *.pyc 22 | 23 | /xcode/Kepler.xcodeproj/project.pbxproj.mergesave 24 | 25 | *~ 26 | -------------------------------------------------------------------------------- /xcode/Kepler_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'iPhoneTestGl' target in the 'iPhoneTestGl' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iPhone SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /src/TextureRect.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // TextureRect.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 7/18/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "TextureRect.h" 10 | #include "cinder/gl/gl.h" 11 | #include "BloomGl.h" 12 | 13 | using namespace ci; 14 | 15 | void TextureRect::draw() 16 | { 17 | bloom::gl::batchRect( mTexture, mArea, mRect ); 18 | } -------------------------------------------------------------------------------- /blocks/BloomTasks/src/TaskQueue.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // TaskQueue.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 8/17/11. 6 | // Copyright 2011 Bloom Studio, Inc. All rights reserved. 7 | // 8 | 9 | #include "TaskQueue.h" 10 | 11 | std::mutex UiTaskQueue::mFunctionsMutex; 12 | std::queue UiTaskQueue::mFunctions; 13 | uint64_t UiTaskQueue::mCompletedTasks = 0; 14 | uint64_t UiTaskQueue::mTotalTasks = 0; 15 | std::set UiTaskQueue::mCanceledIds; 16 | -------------------------------------------------------------------------------- /xcode/fixproject.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | projectfile=`find -d . -name 'project.pbxproj'` 4 | projectdir=`echo *.xcodeproj` 5 | projectfile="${projectdir}/project.pbxproj" 6 | tempfile="${projectdir}/project.pbxproj.out" 7 | savefile="${projectdir}/project.pbxproj.mergesave" 8 | 9 | cat $projectfile | grep -v "<<<<<<< HEAD" | grep -v "=======" | grep -v "^>>>>>>> " > $tempfile 10 | cp $projectfile $savefile 11 | mv $tempfile $projectfile 12 | -------------------------------------------------------------------------------- /src/StringHelpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // StringHelpers.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 8/31/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #ifndef Kepler_StringHelpers_h 10 | #define Kepler_StringHelpers_h 11 | 12 | #include 13 | 14 | namespace bloom { 15 | // because wstring has 32-byte chars on iOS 16 | std::string wstringToUtf8(const std::wstring &s); 17 | std::wstring utf8ToWstring(const std::string &s); 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/Dust.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cinder/Vector.h" 3 | #include "cinder/Color.h" 4 | #include "Node.h" 5 | #include 6 | 7 | class Dust { 8 | public: 9 | Dust(); 10 | Dust( int index, ci::Vec3f pos, ci::Vec3f vel ); 11 | void setup( const ci::Vec3f &camEye ); 12 | void update( const ci::Vec3f &camEye ); 13 | 14 | int mIndex; 15 | ci::Vec3f mPos, mPrevPos; 16 | ci::Vec3f mVel; 17 | ci::Vec3f mAcc; 18 | 19 | ci::Color mColor; 20 | float mRadius; 21 | 22 | float mDecay; 23 | int mAge; 24 | int mLifespan; 25 | float mAgePer; 26 | bool mIsDead; 27 | }; -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "blocks/CinderGestures"] 2 | path = blocks/CinderGestures 3 | url = git@github.com:bloomtime/CinderGestures.git 4 | [submodule "blocks/CinderIPod"] 5 | path = blocks/CinderIPod 6 | url = git@github.com:bloomtime/CinderIPod.git 7 | [submodule "blocks/CinderFlurry"] 8 | path = blocks/CinderFlurry 9 | url = git@github.com:bloomtime/CinderFlurry.git 10 | [submodule "blocks/CinderOrientation"] 11 | path = blocks/CinderOrientation 12 | url = git@github.com:bloomtime/CinderOrientation.git 13 | [submodule "blocks/BloomScene"] 14 | path = blocks/BloomScene 15 | url = git@github.com:bloomtime/BloomScene.git 16 | -------------------------------------------------------------------------------- /src/Shadow.h: -------------------------------------------------------------------------------- 1 | // 2 | // Shadow.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "cinder/Vector.h" 10 | #include "cinder/gl/gl.h" 11 | 12 | class Node; 13 | 14 | class Shadow 15 | { 16 | public: 17 | 18 | Shadow(); 19 | ~Shadow(); 20 | 21 | void setup( Node* node, Node* mParentNode, float camAlpha ); 22 | void draw(); 23 | 24 | private: 25 | 26 | void buildVerts( ci::Vec3f p1, ci::Vec3f p2, ci::Vec3f p3, ci::Vec3f p4 ); 27 | 28 | GLfloat *mShadowVerts; 29 | GLfloat *mShadowTexCoords; 30 | 31 | }; -------------------------------------------------------------------------------- /src/OrbitRing.h: -------------------------------------------------------------------------------- 1 | // 2 | // Rings.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/13/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "cinder/gl/gl.h" 12 | #include "cinder/Vector.h" 13 | 14 | class OrbitRing { 15 | 16 | public: 17 | 18 | OrbitRing(); 19 | ~OrbitRing(); 20 | 21 | void setup(); 22 | void drawLowRes() const; 23 | void drawHighRes() const; 24 | 25 | private: 26 | 27 | struct VertexData { 28 | ci::Vec2f vertex; 29 | ci::Vec2f texture; 30 | }; 31 | 32 | GLuint mLowResVBO, mHighResVBO; 33 | 34 | }; -------------------------------------------------------------------------------- /src/GyroHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // GyroHelper.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/9/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #import 11 | #include "cinder/Quaternion.h" 12 | 13 | class GyroHelper { 14 | public: 15 | 16 | GyroHelper(); 17 | ~GyroHelper(); 18 | 19 | void setup(); 20 | void update(); 21 | 22 | ci::Quatf getQuat() { return mQuat; } 23 | private: 24 | ci::Quatf mQuat; 25 | bool mActive; 26 | 27 | // Objective C 28 | CMMotionManager *motionManager; 29 | CMAttitude *referenceAttitude; 30 | 31 | }; -------------------------------------------------------------------------------- /src/Filter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Filter.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/4/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include "CinderIPod.h" 11 | 12 | // pure virtual "interface" class, Filters must implement tests for PlaylistRefs and TrackRefs 13 | class Filter { 14 | public: 15 | Filter() {} 16 | virtual ~Filter() {} 17 | virtual bool testArtist(ci::ipod::PlaylistRef artist) const = 0; 18 | virtual bool testAlbum(ci::ipod::PlaylistRef album) const = 0; 19 | virtual bool testTrack(ci::ipod::TrackRef track) const = 0; 20 | }; 21 | 22 | typedef std::shared_ptr FilterRef; 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Planetary 2 | == 3 | 4 | For a fresh checkout, do: 5 | 6 | `git submodule init` 7 | `git submodule update` 8 | 9 | And set a `CINDER_PATH_username` variable in the Build Settings corresponding to wherever you have installed Cinder. 10 | 11 | See also 12 | -- 13 | 14 | * [Planetary: collecting and preserving code as a living object](https://www.cooperhewitt.org/object-of-the-day/2013/08/26/planetary-collecting-and-preserving-code-living-object) (Cooper-Hewitt Object of the Day weblog) 15 | * [Planetary object page on the Cooper-Hewitt collections website](http://collection.cooperhewitt.org/objects/35520989/) 16 | * [Planetary extras](https://github.com/cooperhewitt/PlanetaryExtras) 17 | -------------------------------------------------------------------------------- /src/LetterFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // LetterFilter.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/4/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "Filter.h" 12 | #include "CinderIPod.h" 13 | 14 | class LetterFilter : public Filter { 15 | public: 16 | static FilterRef create( char letter ); 17 | bool testArtist( ci::ipod::PlaylistRef artist ) const; 18 | bool testAlbum( ci::ipod::PlaylistRef album ) const; 19 | bool testTrack( ci::ipod::TrackRef track ) const; 20 | private: 21 | LetterFilter( char letter ); 22 | char mLetter; // always uppercase, unless '#' 23 | bool testArtistName(const std::string &name) const; 24 | }; -------------------------------------------------------------------------------- /src/PlanetRing.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlanetRing.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/14/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "cinder/Vector.h" 12 | 13 | class PlanetRing { 14 | 15 | public: 16 | 17 | struct VertexData { 18 | ci::Vec3f vertex; 19 | ci::Vec2f texture; 20 | }; 21 | 22 | PlanetRing() 23 | { 24 | mVerts = NULL; 25 | } 26 | 27 | ~PlanetRing() 28 | { 29 | if (mVerts != NULL) { 30 | delete[] mVerts; 31 | mVerts = NULL; 32 | } 33 | } 34 | 35 | void setup(); 36 | void draw() const; 37 | 38 | private: 39 | 40 | VertexData *mVerts; 41 | 42 | }; -------------------------------------------------------------------------------- /src/Stars.h: -------------------------------------------------------------------------------- 1 | // 2 | // StarGlows.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/13/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | #include "cinder/Vector.h" 13 | 14 | class NodeArtist; 15 | 16 | class Stars { 17 | public: 18 | 19 | Stars(); 20 | 21 | ~Stars(); 22 | 23 | void setup( const std::vector &nodes, 24 | const ci::Vec3f &bbRight, const ci::Vec3f &bbUp, 25 | const float &zoomAlpha ); 26 | void draw(); 27 | 28 | private: 29 | 30 | struct VertexData { 31 | ci::Vec3f vertex; 32 | ci::Vec2f texture; 33 | ci::Vec4f color; 34 | }; 35 | 36 | int mTotalVertices, mPrevTotalVertices; 37 | VertexData *mVerts; 38 | 39 | }; -------------------------------------------------------------------------------- /src/Device.h: -------------------------------------------------------------------------------- 1 | // 2 | // Device.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/9/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include 11 | 12 | namespace bloom { 13 | 14 | bool isIpad2() 15 | { 16 | // http://stackoverflow.com/questions/448162/determine-device-iphone-ipod-touch-with-iphone-sdk/1561920#1561920 17 | // http://www.clintharris.net/2009/iphone-model-via-sysctlbyname/ 18 | size_t size; 19 | sysctlbyname("hw.machine", NULL, &size, NULL, 0); 20 | char *machine = new char[size]; 21 | sysctlbyname("hw.machine", machine, &size, NULL, 0); 22 | bool isIpad2 = (strcmp("iPad1,1",machine) != 0); 23 | delete[] machine; 24 | 25 | return isIpad2; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /src/PlaylistFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlaylistFilter.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/4/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include 11 | #include "Filter.h" 12 | #include "CinderIPod.h" 13 | 14 | class PlaylistFilter : public Filter { 15 | public: 16 | static FilterRef create(ci::ipod::PlaylistRef playlist); 17 | bool testArtist( ci::ipod::PlaylistRef artist ) const; 18 | bool testAlbum( ci::ipod::PlaylistRef album ) const; 19 | bool testTrack( ci::ipod::TrackRef track ) const; 20 | private: 21 | PlaylistFilter(ci::ipod::PlaylistRef playlist); 22 | boost::unordered_set mArtistSet; 23 | boost::unordered_set mAlbumSet; 24 | boost::unordered_set mTrackSet; 25 | }; 26 | -------------------------------------------------------------------------------- /src/Particle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cinder/Vector.h" 3 | #include "cinder/Color.h" 4 | #include "Node.h" 5 | #include "cinder/Quaternion.h" 6 | #include 7 | 8 | class Particle { 9 | public: 10 | Particle(); 11 | Particle( int index, ci::Vec3f pos, ci::Vec3f vel, const ci::Vec3f &bbRight, const ci::Vec3f &bbUp ); 12 | void setup( const ci::Vec3f &bbRight, const ci::Vec3f &bbUp ); 13 | void update( float radius, const ci::Vec3f &bbRight, const ci::Vec3f &bbUp ); 14 | 15 | int mIndex; 16 | ci::Vec3f mPos; 17 | ci::Vec3f mVel; 18 | ci::Vec3f mAcc; 19 | 20 | float mAngle; 21 | float mCosAngle, mSinAngle; 22 | ci::Color mColor; 23 | float mRadius, mRadiusDest; 24 | float mDecay; 25 | int mAge; 26 | float mLifespan; 27 | float mAgePer; 28 | bool mIsDead; 29 | ci::Quatf mQuat; 30 | 31 | bool mIsRetreatingFlare; 32 | }; -------------------------------------------------------------------------------- /src/StarGlows.h: -------------------------------------------------------------------------------- 1 | // 2 | // StarGlows.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/13/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | #include "cinder/Vector.h" 13 | 14 | class NodeArtist; 15 | 16 | class StarGlows { 17 | public: 18 | 19 | StarGlows(); 20 | ~StarGlows(); 21 | 22 | void setup( const std::vector &filteredNodes, 23 | const ci::Vec3f &bbRight, const ci::Vec3f &bbUp, 24 | const float &zoomAlpha ); 25 | void draw(); 26 | 27 | private: 28 | 29 | struct VertexData { 30 | ci::Vec3f vertex; 31 | ci::Vec2f texture; 32 | ci::Vec4f color; // TODO: try uint again? ColorA8u 33 | }; 34 | 35 | int mTotalVertices; 36 | int mPrevTotalVertices; 37 | VertexData *mVerts; 38 | 39 | }; -------------------------------------------------------------------------------- /src/TextureRect.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextureRect.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 7/18/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include "cinder/gl/Texture.h" 11 | #include "cinder/Area.h" 12 | #include "cinder/Rect.h" 13 | #include "BloomNode.h" 14 | 15 | class TextureRect : public BloomNode 16 | { 17 | public: 18 | 19 | TextureRect( const ci::gl::Texture &texture, const ci::Area &area ): mTexture(texture), mArea(area) {} 20 | 21 | virtual void draw(); 22 | 23 | void setRect(const ci::Rectf &rect) { mRect = rect; } 24 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 25 | const ci::Rectf& getRect() const { return mRect; } 26 | 27 | private: 28 | 29 | ci::gl::Texture mTexture; 30 | ci::Area mArea; 31 | ci::Rectf mRect; 32 | }; -------------------------------------------------------------------------------- /src/Stats.h: -------------------------------------------------------------------------------- 1 | // 2 | // Stats.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/10/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "cinder/gl/Texture.h" 12 | #include "cinder/Matrix.h" 13 | #include "cinder/Color.h" 14 | #include "cinder/Font.h" 15 | 16 | class Stats { 17 | 18 | public: 19 | 20 | void setup(const ci::Font &font, const ci::Color &fpsColor, const ci::Color &color); 21 | void update(const float &fps, 22 | const float &playheadTime, 23 | const float &fov, 24 | const float &camDist, 25 | const float &pinchPer, 26 | const float ¤tLevel, 27 | const float &zoom); 28 | void draw(const ci::Matrix44f &orientationMatrix); 29 | 30 | private: 31 | 32 | ci::gl::Texture mParamsTex; 33 | ci::Color mColor, mFpsColor; 34 | ci::Font mFont; 35 | }; -------------------------------------------------------------------------------- /src/Dust.cpp: -------------------------------------------------------------------------------- 1 | #include "Dust.h" 2 | #include "cinder/Rand.h" 3 | #include "cinder/gl/gl.h" 4 | #include "cinder/app/AppBasic.h" 5 | 6 | using namespace ci; 7 | using std::vector; 8 | 9 | Dust::Dust() 10 | { 11 | } 12 | 13 | Dust::Dust( int index, Vec3f pos, Vec3f vel ) 14 | { 15 | mIndex = index; 16 | mLifespan = Rand::randInt( 50, 100 ); 17 | mIsDead = false; 18 | 19 | setup( Vec3f( 0.0f, 0.0f, 0.0f ) ); 20 | } 21 | 22 | void Dust::setup( const Vec3f &camEye ) 23 | { 24 | Vec3f randVec = Rand::randVec3f(); 25 | 26 | mPos = randVec; 27 | 28 | mPrevPos = mPos; 29 | mVel = randVec * Rand::randFloat( 0.004f, 0.00675f ); 30 | mDecay = 0.98f; 31 | mAge = 0; 32 | } 33 | 34 | void Dust::update( const Vec3f &camEye ) 35 | { 36 | mPrevPos = mPos; 37 | mPos += mVel; 38 | mAge ++; 39 | mAgePer = 1.0f - mAge/(float)mLifespan; 40 | if( mAge > mLifespan ){ 41 | setup( camEye ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/BloomSphere.h: -------------------------------------------------------------------------------- 1 | // 2 | // BloomSphere.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/12/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "cinder/gl/gl.h" 12 | 13 | namespace bloom { 14 | 15 | class BloomSphere 16 | { 17 | public: 18 | 19 | struct VertexData { 20 | ci::Vec3f vertex; 21 | // no normal, normal == vertex 22 | ci::Vec2f texture; 23 | }; 24 | 25 | BloomSphere(): mInited(false) {} 26 | ~BloomSphere() { 27 | if (mInited) { 28 | glDeleteBuffers(1, &mVBO); 29 | } 30 | } 31 | 32 | void setup( int segments ); 33 | void draw(); 34 | 35 | private: 36 | 37 | bool mInited; 38 | GLuint mVBO; 39 | int mNumVerts; 40 | 41 | }; 42 | 43 | } -------------------------------------------------------------------------------- /src/Constellation.h: -------------------------------------------------------------------------------- 1 | // 2 | // Constellation.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/14/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | #include "cinder/Vector.h" 13 | #include "NodeArtist.h" 14 | 15 | class Constellation 16 | { 17 | 18 | public: 19 | 20 | struct VertexData { 21 | ci::Vec3f vertex; 22 | ci::Vec2f texture; 23 | }; 24 | 25 | Constellation() 26 | { 27 | mPrevTotalConstellationVertices = -1; 28 | mConstellationVerts = NULL; 29 | } 30 | ~Constellation() 31 | { 32 | if (mConstellationVerts != NULL) { 33 | delete[] mConstellationVerts; 34 | mConstellationVerts = NULL; 35 | } 36 | } 37 | 38 | void setup( const vector &filteredNodes ); 39 | void draw( const float &alpha ) const; 40 | 41 | private: 42 | 43 | std::vector mConstellation; 44 | std::vector mConstellationDistances; 45 | int mTotalConstellationVertices; 46 | int mPrevTotalConstellationVertices; 47 | VertexData *mConstellationVerts; 48 | 49 | }; 50 | -------------------------------------------------------------------------------- /src/StringHelpers.mm: -------------------------------------------------------------------------------- 1 | // 2 | // StringHelpers.mm 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 8/31/11. 6 | // Copyright 2011 Bloom Studio, Inc. All rights reserved. 7 | // 8 | 9 | #include "StringHelpers.h" 10 | 11 | using namespace std; 12 | 13 | namespace bloom { 14 | 15 | // with thanks to Arial Malka 16 | // http://forum.libcinder.org/#Topic/23286000000959252 17 | 18 | string wstringToUtf8(const wstring &s) 19 | { 20 | NSString *utf32NS = [[NSString alloc] initWithBytes: s.data() 21 | length: s.size() * sizeof(wchar_t) 22 | encoding: NSUTF32LittleEndianStringEncoding]; 23 | string utf8 = string([utf32NS UTF8String]); 24 | [utf32NS release]; 25 | return utf8; 26 | } 27 | 28 | wstring utf8ToWstring(const string &s) 29 | { 30 | NSString *utf8NS = [[NSString alloc] initWithUTF8String: s.c_str()]; 31 | wstring utf32 = wstring(reinterpret_cast([utf8NS cStringUsingEncoding:NSUTF32LittleEndianStringEncoding])); 32 | [utf8NS release]; 33 | return utf32; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/PlaylistFilter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // PlaylistFilter.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/4/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "PlaylistFilter.h" 10 | 11 | FilterRef PlaylistFilter::create(ci::ipod::PlaylistRef playlist) 12 | { 13 | return FilterRef( new PlaylistFilter( playlist ) ); 14 | } 15 | 16 | PlaylistFilter::PlaylistFilter(ci::ipod::PlaylistRef playlist) 17 | { 18 | for( ci::ipod::Playlist::Iter i = playlist->begin(); i != playlist->end(); i++ ){ 19 | mArtistSet.insert( (*i)->getArtistId() ); 20 | mAlbumSet.insert( (*i)->getAlbumId() ); 21 | mTrackSet.insert( (*i)->getItemId() ); 22 | } 23 | } 24 | 25 | bool PlaylistFilter::testArtist(ci::ipod::PlaylistRef artist) const 26 | { 27 | return mArtistSet.find( artist->getArtistId() ) != mArtistSet.end(); 28 | } 29 | 30 | bool PlaylistFilter::testAlbum(ci::ipod::PlaylistRef album) const 31 | { 32 | return mAlbumSet.find( album->getAlbumId() ) != mAlbumSet.end(); 33 | } 34 | 35 | bool PlaylistFilter::testTrack(ci::ipod::TrackRef track) const 36 | { 37 | return mTrackSet.find( track->getItemId() ) != mTrackSet.end(); 38 | } 39 | -------------------------------------------------------------------------------- /src/TextLabel.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // TextLabel.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "TextLabel.h" 10 | #include "cinder/gl/gl.h" 11 | #include "cinder/Text.h" 12 | #include "BloomGl.h" 13 | 14 | using namespace std; 15 | using namespace ci; 16 | using namespace ci::app; 17 | 18 | void TextLabel::setText(string text) 19 | { 20 | if (mText != text) { 21 | mText = text; 22 | updateTexture(); 23 | } 24 | } 25 | 26 | void TextLabel::updateTexture() 27 | { 28 | TextLayout layout; 29 | layout.setFont( mFont ); 30 | layout.setColor( mColor ); 31 | layout.addLine( mText ); 32 | mTexture = layout.render( true, false ); 33 | } 34 | 35 | void TextLabel::draw() 36 | { 37 | if (mTexture) { 38 | bloom::gl::batchRect( mTexture, mRect.getUpperLeft() ); 39 | } 40 | } 41 | 42 | bool TextLabel::touchBegan( TouchEvent::Touch touch ) 43 | { 44 | return mRect.contains( globalToLocal( touch.getPos() ) ); 45 | } 46 | 47 | bool TextLabel::touchEnded( TouchEvent::Touch touch ) 48 | { 49 | return mRect.contains( globalToLocal( touch.getPos() ) ); 50 | } 51 | -------------------------------------------------------------------------------- /src/TextLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextLabel.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include 11 | #include "cinder/Font.h" 12 | #include "cinder/Color.h" 13 | #include "cinder/gl/Texture.h" 14 | #include "cinder/Rect.h" 15 | #include "BloomNode.h" 16 | 17 | class TextLabel : public BloomNode { 18 | 19 | public: 20 | 21 | TextLabel(const int &id, const ci::Font &font, const ci::Color &color): BloomNode(id), mFont(font), mColor(color) {} 22 | ~TextLabel() {} 23 | 24 | virtual bool touchBegan(ci::app::TouchEvent::Touch touch); 25 | virtual bool touchEnded(ci::app::TouchEvent::Touch touch); 26 | virtual void draw(); 27 | 28 | void setText(std::string text); 29 | 30 | void setRect(const ci::Rectf &rect) { mRect = rect; } 31 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 32 | const ci::Rectf& getRect() const { return mRect; } 33 | 34 | private: 35 | 36 | void updateTexture(); 37 | 38 | ci::Font mFont; 39 | ci::Color mColor; 40 | std::string mText; 41 | ci::Rectf mRect; 42 | 43 | ci::gl::Texture mTexture; 44 | 45 | }; -------------------------------------------------------------------------------- /src/Data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Data.h 3 | * Kepler 4 | * 5 | * Created by Robert Hodgin on 2/25/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include "CinderIPod.h" // for PlaylistRef 14 | 15 | class Data { 16 | public: 17 | 18 | enum LoadState { LoadStateDefault, LoadStateLoading, LoadStatePending, LoadStateComplete }; 19 | 20 | Data(): mState(LoadStateDefault) {}; 21 | ~Data() {}; 22 | 23 | void setup(); 24 | void update(); 25 | 26 | std::vector mArtists; 27 | std::vector mPlaylists; 28 | 29 | std::map< char, float > mNumArtistsPerChar; 30 | float mNormalizedArtistsPerChar[27]; 31 | 32 | LoadState getState() { return mState; } 33 | 34 | float getArtistProgress() { return mArtistProgress; } 35 | float getPlaylistProgress() { return mPlaylistProgress; } 36 | 37 | void artistProgress(float p) { mArtistProgress = p; } 38 | void playlistProgress(float p) { mPlaylistProgress = p; } 39 | 40 | private: 41 | 42 | void backgroundInit(); 43 | 44 | float mArtistProgress, mPlaylistProgress; 45 | 46 | LoadState mState; 47 | std::vector mPendingArtists; 48 | std::vector mPendingPlaylists; 49 | 50 | }; 51 | -------------------------------------------------------------------------------- /src/NotificationOverlay.h: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationOverlay.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/2/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | #include "cinder/gl/gl.h" 13 | #include "cinder/gl/Texture.h" 14 | #include "cinder/Area.h" 15 | #include "BloomNode.h" 16 | 17 | class NotificationOverlay : public BloomNode { 18 | 19 | public: 20 | 21 | NotificationOverlay(); 22 | ~NotificationOverlay(); 23 | 24 | void setup( const ci::Font &font ); 25 | void update(); 26 | void draw(); 27 | 28 | void show( const ci::gl::Texture &texture, const ci::Area &srcRect, const std::string &message ); 29 | void show( const ci::gl::Texture &texture1, const ci::Area &srcRect1, const ci::Area &srcRect2, const std::string &message ); 30 | void showLetter( const char &c, const std::string &message, const ci::Font &hugeFont ); 31 | void hide(); 32 | 33 | private: 34 | 35 | bool mSetup; 36 | bool mActive; 37 | float mFadeDelay, mFadeDuration, mLastShowTime; 38 | ci::gl::Texture mCurrentTexture; 39 | ci::Area mCurrentSrcArea; 40 | ci::Area mCurrentSecondSrcArea; 41 | std::string mCurrentMessage; 42 | ci::Rectf mMessageRect, mIconRect; 43 | float mAlpha; 44 | ci::Font mFont; 45 | ci::gl::Texture mMessageTexture; 46 | 47 | }; 48 | -------------------------------------------------------------------------------- /src/TimeLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TimeLabel.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include 11 | #include "cinder/Font.h" 12 | #include "cinder/Color.h" 13 | #include "cinder/gl/Texture.h" 14 | #include "cinder/Rect.h" 15 | #include "cinder/Utilities.h" 16 | #include "BloomNode.h" 17 | 18 | using namespace ci; 19 | using namespace std; 20 | 21 | class TimeLabel : public BloomNode { 22 | 23 | public: 24 | 25 | TimeLabel(const int &id, const ci::Font &font, const ci::Color &color): BloomNode(id), mFont(font), mColor(color), mSeconds(-1000000) {} 26 | ~TimeLabel() {} 27 | 28 | virtual bool touchBegan(ci::app::TouchEvent::Touch touch); 29 | virtual bool touchEnded(ci::app::TouchEvent::Touch touch); 30 | virtual void draw(); 31 | 32 | void setSeconds(int seconds); 33 | 34 | void setRect(const ci::Rectf &rect) { mRect = rect; } 35 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 36 | const ci::Rectf& getRect() const { return mRect; } 37 | 38 | private: 39 | 40 | void updateTexture(); 41 | 42 | ci::Font mFont; 43 | ci::Color mColor; 44 | ci::Rectf mRect; 45 | 46 | int mSeconds; 47 | 48 | ci::gl::Texture mTexture, mHyphenTexture; 49 | 50 | }; -------------------------------------------------------------------------------- /src/LoadingScreen.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingScreen.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 3/17/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "cinder/gl/Texture.h" 12 | #include "BloomNode.h" 13 | 14 | class LoadingScreen : public BloomNode { 15 | public: 16 | void setup( const ci::gl::Texture &planetaryTex, const ci::gl::Texture &planetTex, 17 | const ci::gl::Texture &backgroundTex, const ci::gl::Texture &starGlowTex ); 18 | void draw(); 19 | void update(); 20 | bool touchBegan( ci::app::TouchEvent::Touch touch ) { return isVisible(); }; 21 | bool touchMoved( ci::app::TouchEvent::Touch touch ) { return isVisible(); }; 22 | bool touchEnded( ci::app::TouchEvent::Touch touch ) { return isVisible(); }; 23 | void setTextureProgress( float prop ); 24 | void setArtistProgress( float prop ); 25 | void setPlaylistProgress( float prop ); 26 | bool isComplete(); // returns true if all the progress bars are done animating to their dests 27 | private: 28 | float mTextureProgress, mTextureProgressDest; 29 | float mArtistProgress, mArtistProgressDest; 30 | float mPlaylistProgress, mPlaylistProgressDest; 31 | ci::gl::Texture mStarGlowTex; 32 | ci::gl::Texture mPlanetaryTex; 33 | ci::gl::Texture mPlanetTex; 34 | ci::gl::Texture mBackgroundTex; 35 | ci::Vec2f mInterfaceSize; 36 | }; -------------------------------------------------------------------------------- /bin/src2pdf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # See also: 4 | # http://linux.die.net/man/1/enscript 5 | # http://ansuz.sooke.bc.ca/page/fonts#ocra 6 | # http://sourceforge.jp/projects/tsukurimashou/downloads/56948/ocr-0.2.zip/ 7 | 8 | PYTHON=`which python` 9 | ENSCRIPT=`which enscript` 10 | PSTOPDF=`which pstopdf` 11 | 12 | WHOAMI=`${PYTHON} -c 'import os, sys; print os.path.realpath(sys.argv[1])' $0` 13 | BIN=`dirname ${WHOAMI}` 14 | ROOT=`dirname ${BIN}` 15 | 16 | PDF=$1 17 | 18 | if [ -z $PDF ] 19 | then 20 | PDF="${ROOT}/planetary.pdf" 21 | fi 22 | 23 | if [ -f $PDF ] 24 | then 25 | echo "${PDF} already exists, removing in 5 seconds..." 26 | sleep 5 27 | rm ${PDF} 28 | fi 29 | 30 | echo "writing source code to ${PDF}" 31 | 32 | # Note that we are excluding blocks/CinderFlurry/lib/FlurryLib/libFlurry.a 33 | 34 | ${ENSCRIPT} -v -r --media=Legal --toc --margins=30:30:50:50 --non-printable-format=octal -p - --line-numbers --header='6814.1.2013|$N|$%/$=' --word-wrap -O -F 'OCRA6' -f 'OCRA6' ${ROOT}/src/* ${ROOT}/blocks/BloomScene/include/* ${ROOT}/blocks/BloomScene/src/* ${ROOT}/blocks/BloomTasks/src/* ${ROOT}/blocks/CinderFlurry/include/* ${ROOT}/blocks/CinderFlurry/lib/FlurryLib/*.h ${ROOT}/blocks/CinderFlurry/src/* ${ROOT}/blocks/CinderGestures/include/* ${ROOT}/blocks/CinderIPod/include/* ${ROOT}/blocks/CinderIPod/src/* ${ROOT}/blocks/CinderOrientation/include/* ${ROOT}/blocks/CinderOrientation/src/* | ${PSTOPDF} -i -o ${PDF} 35 | 36 | exit 37 | -------------------------------------------------------------------------------- /src/Vignette.h: -------------------------------------------------------------------------------- 1 | // 2 | // Vignette.h 3 | // Kepler 4 | // 5 | // Created by Robert Hodgin on 7/20/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "cinder/app/AppCocoaTouch.h" 12 | #include "cinder/Function.h" 13 | #include "cinder/Vector.h" 14 | #include "cinder/gl/gl.h" 15 | #include "cinder/gl/Texture.h" 16 | #include "cinder/Rect.h" 17 | #include "cinder/Color.h" 18 | #include "BloomNode.h" 19 | 20 | class Vignette : public BloomNode { 21 | public: 22 | Vignette() {} 23 | ~Vignette() 24 | { 25 | delete[] mVerts; 26 | } 27 | 28 | void setup( const ci::gl::Texture &tex ); 29 | void update(); 30 | void draw(); 31 | 32 | void setShowing( bool b ); 33 | bool isShowing(){ return mShowing; } 34 | 35 | float getScale() { return mScale; } 36 | 37 | template 38 | ci::CallbackId registerToggled( T *obj, bool ( T::*callback )( bool ) ){ 39 | return mCallbacksToggled.registerCb(std::bind1st( std::mem_fun( callback ), obj ) ); 40 | } 41 | 42 | private: 43 | 44 | struct VertexData { 45 | ci::Vec2f vertex; 46 | ci::Vec2f texture; 47 | }; 48 | 49 | void updateVerts(); 50 | 51 | ci::gl::Texture mTex; 52 | 53 | float mScale; 54 | 55 | bool mShowing; 56 | 57 | int mTotalVertices; 58 | VertexData *mVerts; 59 | 60 | ci::Vec2f mInterfaceSize, mInterfaceCenter; 61 | 62 | ci::CallbackMgr mCallbacksToggled; 63 | }; 64 | -------------------------------------------------------------------------------- /src/ParticleController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Particle.h" 3 | #include "Dust.h" 4 | #include "Node.h" 5 | #include 6 | 7 | class ParticleController { 8 | public: 9 | 10 | struct ParticleVertex { 11 | ci::Vec3f vertex; 12 | ci::Vec2f texture; 13 | ci::Vec4f color; 14 | }; 15 | 16 | struct DustVertex { 17 | ci::Vec3f vertex; 18 | ci::Vec4f color; 19 | }; 20 | 21 | ParticleController(); 22 | void update( const ci::Vec3f &camEye, float radius, const ci::Vec3f &bbRight, const ci::Vec3f &bbUp ); 23 | void buildParticleVertexArray( float scaleOffset, ci::Color c, float eclipseStrength ); 24 | void buildDustVertexArray( float scaleOffset, Node *node, float pinchAlphaOffset, float dustAlpha ); 25 | void drawParticleVertexArray( Node *node, float multi ); 26 | void drawDustVertexArray( Node *node, float multi ); 27 | void addParticles( int amt ); 28 | void removeParticles( int amt ); 29 | void addDusts( int amt ); 30 | 31 | // TODO: consider dynamic VBOs or VAOs for these arrays 32 | 33 | std::list mParticles; 34 | int mTotalParticleVertices; 35 | int mPrevTotalParticleVertices; // so we only recreate frames 36 | ParticleVertex *mParticleVerts; // TODO: consider POINT_SPRITE stuff for these? 37 | 38 | std::list mDusts; 39 | int mTotalDustVertices; 40 | int mPrevTotalDustVertices; // so we only recreate frames 41 | DustVertex *mDustVerts; 42 | 43 | ci::Vec3f mBbRight; 44 | ci::Vec3f mBbUp; 45 | 46 | }; -------------------------------------------------------------------------------- /src/NodeArtist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NodeArtist.h 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 1/21/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "CinderIPod.h" 13 | #include "Node.h" 14 | #include "cinder/Vector.h" 15 | 16 | class NodeArtist : public Node 17 | { 18 | public: 19 | NodeArtist( int index, const ci::Font &font, const ci::Font &smallFont, const ci::Surface &hiResSurfaces, const ci::Surface &loResSurfaces, const ci::Surface &noAlbumArt ); 20 | 21 | void update( float param1, float param2 ); 22 | void drawEclipseGlow(); 23 | void drawStarGlow( const ci::Vec3f &camEye, const ci::Vec3f &camNormal, const ci::gl::Texture &tex ); 24 | void drawExtraGlow( const ci::Vec3f &camEye, const ci::gl::Texture &texGlow, const ci::gl::Texture &texCore ); 25 | void drawPlanet( const ci::gl::Texture &tex ); 26 | void drawAtmosphere( const ci::Vec3f &camEye, const ci::Vec2f ¢er, const ci::gl::Texture &tex, const ci::gl::Texture &directionalTex, float pinchAlphaPer, float scaleSliderOffset ); 27 | 28 | void select(); 29 | void setChildOrbitRadii(); 30 | std::string getName(); 31 | uint64_t getId(); 32 | void setData( ci::ipod::PlaylistRef playlist ); 33 | int getNumAlbums(){ return mNumAlbums; } 34 | ci::ipod::PlaylistRef getPlaylist() { return mPlaylist; } 35 | 36 | private: 37 | void setColors(); 38 | ci::ipod::PlaylistRef mPlaylist; 39 | int mNumAlbums; 40 | uint64_t mId; 41 | }; 42 | 43 | bool yearSortFunc(Node* a, Node* b); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Smithsonian Institution 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | Neither the name of the Smithsonian Institution nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/Particle.cpp: -------------------------------------------------------------------------------- 1 | #include "Particle.h" 2 | #include "cinder/Rand.h" 3 | #include "cinder/gl/gl.h" 4 | #include "cinder/app/AppBasic.h" 5 | 6 | using namespace ci; 7 | using std::vector; 8 | 9 | Particle::Particle() 10 | { 11 | } 12 | 13 | Particle::Particle( int index, Vec3f pos, Vec3f vel, const Vec3f &bbRight, const Vec3f &bbUp ) 14 | { 15 | mIndex = index; 16 | mColor = ColorA( 1.0f, 1.0f, 1.0f, 1.0f ); 17 | 18 | mIsDead = false; 19 | mAngle = Rand::randFloat( 6.2832f ); 20 | mCosAngle = (float)cos( mAngle ); 21 | mSinAngle = (float)sin( mAngle ); 22 | 23 | setup( bbRight, bbUp ); 24 | } 25 | 26 | void Particle::setup( const Vec3f &bbRight, const Vec3f &bbUp ) 27 | { 28 | mLifespan = pow( Rand::randFloat( 0.5f, 1.0f ), 2.0f ); 29 | mRadius = Rand::randFloat( 0.2f, 0.3f ); 30 | if( Rand::randFloat() < 0.01f ){ 31 | mLifespan *= Rand::randFloat( 100.0f, 150.0f ); 32 | mRadius *= 2.0f; 33 | } else { 34 | mLifespan *= Rand::randFloat( 100.0f, 400.0f ); 35 | } 36 | 37 | mPos = Rand::randVec3f() * 0.95f; 38 | mVel = mPos * ( Rand::randFloat( 0.0075f, 0.02f ) * ( mRadius/5.0f ) ); 39 | mAcc = Rand::randVec3f() * 0.01f; 40 | mAge = 0; 41 | mAgePer = 0.0f; 42 | mQuat = Quatf( mPos, Rand::randFloat( M_PI * 2.0f ) ); 43 | } 44 | 45 | void Particle::update( float radius, const Vec3f &bbRight, const Vec3f &bbUp ) 46 | { 47 | mAgePer = 1.0f - sqrt( (float)mAge/(float)mLifespan ); 48 | 49 | // mPos = ( bbRight * mCosAngle + bbUp * mSinAngle ) * ( radius + mAge * 0.00015f ); 50 | //mPrevPos = mPos; 51 | // mPos += mVel; 52 | mAge ++; 53 | if( mAge > mLifespan ){ 54 | setup( bbRight, bbUp ); 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/LetterFilter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // LetterFilter.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/4/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "LetterFilter.h" 10 | #include // for toupper(char), isalpha(char), etc. 11 | #include 12 | #include // for boost::to_upper(std::string) 13 | 14 | FilterRef LetterFilter::create(char letter) 15 | { 16 | return FilterRef( new LetterFilter( letter ) ); 17 | } 18 | 19 | LetterFilter::LetterFilter(char letter) 20 | { 21 | mLetter = letter; 22 | if (mLetter != '#' && !isupper(mLetter)) { 23 | mLetter = static_cast ( toupper( mLetter ) ); 24 | } 25 | } 26 | 27 | bool LetterFilter::testArtist(ci::ipod::PlaylistRef artist) const 28 | { 29 | return testArtistName(artist->getArtistName()); 30 | } 31 | 32 | bool LetterFilter::testAlbum(ci::ipod::PlaylistRef album) const 33 | { 34 | return testArtistName(album->getArtistName()); 35 | } 36 | 37 | bool LetterFilter::testTrack(ci::ipod::TrackRef track) const 38 | { 39 | return testArtistName(track->getArtist()); 40 | } 41 | 42 | bool LetterFilter::testArtistName(const std::string &name) const 43 | { 44 | if (mLetter != '#') { 45 | char firstLetter = name[0]; 46 | if (name.length() > 5) { 47 | std::string the = boost::to_upper_copy(name.substr( 0, 4 )); 48 | if( the == "THE " ){ 49 | firstLetter = name[4]; 50 | } 51 | } 52 | return isalpha(firstLetter) && toupper(firstLetter) == mLetter; 53 | } 54 | else { 55 | return !isalpha( name[0] ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/PlanetRing.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // PlanetRing.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/14/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "PlanetRing.h" 10 | #include "cinder/gl/gl.h" 11 | #include "cinder/Vector.h" 12 | 13 | using namespace ci; 14 | using namespace std; 15 | 16 | void PlanetRing::setup() 17 | { 18 | if (mVerts != NULL) { 19 | delete[] mVerts; 20 | } 21 | 22 | mVerts = new VertexData[6]; 23 | int i = 0; 24 | float w = 1.0f; 25 | 26 | mVerts[i].vertex = Vec3f( -w, 0.0f, -w ); 27 | mVerts[i].texture = Vec2f( 0.0f, 0.0f ); 28 | i++; 29 | 30 | mVerts[i].vertex = Vec3f( w, 0.0f, -w ); 31 | mVerts[i].texture = Vec2f( 1.0f, 0.0f ); 32 | i++; 33 | 34 | mVerts[i].vertex = Vec3f( w, 0.0f, w ); 35 | mVerts[i].texture = Vec2f( 1.0f, 1.0f ); 36 | i++; 37 | 38 | mVerts[i].vertex = Vec3f( -w, 0.0f, -w ); 39 | mVerts[i].texture = Vec2f( 0.0f, 0.0f ); 40 | i++; 41 | 42 | mVerts[i].vertex = Vec3f( w, 0.0f, w ); 43 | mVerts[i].texture = Vec2f( 1.0f, 1.0f ); 44 | i++; 45 | 46 | mVerts[i].vertex = Vec3f( -w, 0.0f, w ); 47 | mVerts[i].texture = Vec2f( 0.0f, 1.0f ); 48 | i++; 49 | } 50 | 51 | void PlanetRing::draw() const 52 | { 53 | glEnableClientState( GL_VERTEX_ARRAY ); 54 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 55 | glVertexPointer( 3, GL_FLOAT, sizeof(VertexData), mVerts ); 56 | glTexCoordPointer( 2, GL_FLOAT, sizeof(VertexData), &mVerts[0].texture ); 57 | glDrawArrays( GL_TRIANGLES, 0, 6 ); 58 | glDisableClientState( GL_VERTEX_ARRAY ); 59 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 60 | } 61 | -------------------------------------------------------------------------------- /src/ScrollingLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollingLabel.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include 11 | #include "cinder/Font.h" 12 | #include "cinder/Color.h" 13 | #include "cinder/gl/Texture.h" 14 | #include "cinder/Rect.h" 15 | #include "BloomNode.h" 16 | 17 | class ScrollingLabel : public BloomNode { 18 | 19 | public: 20 | 21 | ScrollingLabel(const int &id, const ci::Font &font, const ci::Color &color): BloomNode(id), mFont(font), mColor(color) {} 22 | ~ScrollingLabel() {} 23 | 24 | virtual bool touchBegan(ci::app::TouchEvent::Touch touch); 25 | virtual bool touchEnded(ci::app::TouchEvent::Touch touch); 26 | virtual void update(); 27 | virtual void draw(); 28 | 29 | void setText(std::string text); 30 | 31 | bool isScrollingText() { return mIsScrolling; } 32 | 33 | void setColor(ci::Color color) { mColor = color; updateTexture(); } 34 | 35 | void setRect(const ci::Rectf &rect) { mRect = rect; } 36 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 37 | const ci::Rectf& getRect() const { return mRect; } 38 | 39 | float getFontHeight() { return mFont.getAscent() + mFont.getDescent(); } 40 | 41 | private: 42 | 43 | void updateTexture(); 44 | 45 | ci::Font mFont; 46 | ci::Color mColor; 47 | ci::Rectf mRect; 48 | 49 | ci::Area mFirstArea, mSecondArea; 50 | 51 | std::string mText; 52 | float mLastChangeTime; 53 | 54 | ci::gl::Texture mTexture; 55 | 56 | bool mIsScrolling; 57 | 58 | }; -------------------------------------------------------------------------------- /src/Stats.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Stats.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/10/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "Stats.h" 10 | #include 11 | #include "cinder/gl/gl.h" 12 | #include "cinder/Text.h" 13 | 14 | using namespace std; 15 | using namespace ci; 16 | 17 | void Stats::setup(const Font &font, const Color &fpsColor, const Color &color) 18 | { 19 | mFont = font; 20 | mFpsColor = fpsColor; 21 | mColor = color; 22 | } 23 | 24 | void Stats::update(const float &fps, 25 | const float &playheadTime, 26 | const float &fov, 27 | const float &camDist, 28 | const float &pinchPer, 29 | const float ¤tLevel, 30 | const float &zoom) 31 | { 32 | stringstream s; 33 | TextLayout layout; 34 | layout.setFont( mFont ); 35 | layout.setColor( mColor ); 36 | 37 | s.str(""); 38 | s << "FPS: " << fps; 39 | layout.addLine( s.str() ); 40 | 41 | // s.str(""); 42 | // s << "FOV: " << fov; 43 | // layout.addLine( s.str() ); 44 | // 45 | // s.str(""); 46 | // s << "mCamDist: " << camDist; 47 | // layout.addLine( s.str() ); 48 | // 49 | // s.str(""); 50 | // s << "mPinchTotalDest: " << pinchPer; 51 | // layout.addLine( s.str() ); 52 | 53 | mParamsTex = gl::Texture( layout.render( true, false ) ); 54 | } 55 | 56 | void Stats::draw(const Matrix44f &mtx) 57 | { 58 | if (mParamsTex) { 59 | glPushMatrix(); 60 | glMultMatrixf( mtx ); 61 | gl::color( ColorA( Color::white(), 0.1f ) ); 62 | gl::draw( mParamsTex, Vec2f( 23.0f, 15.0f ) ); 63 | glPopMatrix(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/GyroHelper.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // GyroHelper.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/9/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "GyroHelper.h" 10 | 11 | GyroHelper::GyroHelper() 12 | { 13 | mActive = false; // call setup() to activate 14 | } 15 | 16 | GyroHelper::~GyroHelper() 17 | { 18 | if (mActive) { 19 | [motionManager stopDeviceMotionUpdates]; 20 | [motionManager release]; 21 | [referenceAttitude release]; 22 | } 23 | } 24 | 25 | void GyroHelper::setup() 26 | { 27 | motionManager = [[CMMotionManager alloc] init]; 28 | [motionManager startDeviceMotionUpdates]; 29 | 30 | CMDeviceMotion *dm = motionManager.deviceMotion; 31 | referenceAttitude = [dm.attitude retain]; 32 | 33 | mActive = true; 34 | } 35 | 36 | void GyroHelper::update() 37 | { 38 | if (!mActive) return; 39 | 40 | CMQuaternion quat; 41 | 42 | CMDeviceMotion *deviceMotion = motionManager.deviceMotion; 43 | CMAttitude *attitude = deviceMotion.attitude; 44 | 45 | // If we have a reference attitude, multiply attitude by its inverse 46 | // After this call, attitude will contain the rotation from referenceAttitude 47 | // to the current orientation instead of from the fixed reference frame to the 48 | // current orientation 49 | /* 50 | if (referenceAttitude != nil) { 51 | [attitude multiplyByInverseOfAttitude:referenceAttitude]; 52 | } 53 | */ 54 | 55 | quat = attitude.quaternion; 56 | 57 | // flip w around so quat can be applied to camera eye/up 58 | // flip y around because who knows why 59 | mQuat.set( -quat.w, quat.x, -quat.y, quat.z ); 60 | } -------------------------------------------------------------------------------- /src/BloomGl.h: -------------------------------------------------------------------------------- 1 | // 2 | // GlExtras.h 3 | // Kepler 4 | // 5 | // Created by Robert Hodgin on 4/7/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include "cinder/Cinder.h" 14 | #include "cinder/Rect.h" 15 | #include "cinder/gl/gl.h" 16 | #include "cinder/gl/Texture.h" 17 | #include 18 | 19 | namespace bloom { namespace gl { 20 | 21 | void drawBillboard( const ci::Vec3f &pos, const ci::Vec2f &scale, float rotationDegrees, const ci::Vec3f &bbRight, const ci::Vec3f &bbUp ); 22 | void drawSphericalBillboard( const ci::Vec3f &camEye, const ci::Vec3f &objPos, const ci::Vec2f &scale, float rotationDegrees ); 23 | void drawSphericalRotatedBillboard( const ci::Vec3f &pos, const ci::Vec3f &lookAt, const ci::Vec3f &turnAt, const ci::Vec2f &scale ); 24 | 25 | // hat tip http://craiggiles.wordpress.com/2009/08/03/opengl-es-batch-rendering-on-the-iphone/ 26 | 27 | struct VertexData { 28 | ci::Vec2f vertex; 29 | ci::Vec2f texture; 30 | }; 31 | 32 | struct Batch { 33 | ci::gl::Texture texture; 34 | std::vector vertices; 35 | }; 36 | 37 | typedef std::shared_ptr BatchRef; 38 | 39 | extern boost::unordered_map batchByTex; 40 | extern std::vector batches; 41 | 42 | void beginBatch(); 43 | void batchRect( const ci::gl::Texture &tex, const ci::Vec2f &pos ); 44 | void batchRect( const ci::gl::Texture &tex, const ci::Rectf &srcRect, const ci::Rectf &dstRect ); 45 | void batchRect( const ci::gl::Texture &tex, const ci::Area &srcArea, const ci::Rectf &dstRect ); 46 | void endBatch(); 47 | 48 | } } 49 | -------------------------------------------------------------------------------- /src/Globals.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Globals.h 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 1/20/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "cinder/Color.h" 13 | 14 | static const double TWO_PI = M_PI * 2.0; 15 | 16 | // TODO: enum for these? 17 | // TODO: move into State.h? 18 | static const int G_ALPHA_LEVEL = 1; 19 | static const int G_ARTIST_LEVEL = 2; 20 | static const int G_ALBUM_LEVEL = 3; 21 | static const int G_TRACK_LEVEL = 4; 22 | static const int G_NUM_LEVELS = 5; 23 | 24 | static const float G_INIT_CAM_DIST = 250.0f; 25 | static const int G_NUM_PLANET_TYPES = 5; 26 | static const int G_NUM_PLANET_TYPE_OPTIONS = 3; 27 | static const int G_NUM_CLOUD_TYPES = 5; 28 | 29 | static const float G_MIN_FOV = 55.0f; 30 | static const float G_DEFAULT_FOV = 60.0f; 31 | static const float G_MAX_FOV = 80.0f; 32 | 33 | static const float G_DEFAULT_ARCBALL_RADIUS = 500.0f; 34 | 35 | static const int G_RING_LOW_RES = 250; 36 | static const int G_RING_HIGH_RES = 500; 37 | 38 | static const float G_SKYDOME_RADIUS = 1000.0f; 39 | 40 | static const int G_TOTAL_HELP_CALLOUTS = 8; 41 | 42 | static const ci::Color GREY = ci::Color( 0.1f, 0.1f, 0.15f ); 43 | static const ci::Color BLUE = ci::Color( 0.1f, 0.2f, 0.5f ); 44 | static const ci::Color BRIGHT_BLUE = ci::Color( 0.4f, 0.8f, 1.0f ); 45 | static const ci::Color BRIGHT_YELLOW = ci::Color( 1.0f, 0.9f, 0.35f ); 46 | 47 | 48 | // TODO: move into State.h 49 | extern float G_ZOOM; 50 | extern int G_CURRENT_LEVEL; 51 | extern bool G_DEBUG; 52 | extern bool G_AUTO_MOVE; 53 | extern bool G_SHOW_SETTINGS; 54 | extern bool G_DRAW_RINGS; 55 | extern bool G_DRAW_TEXT; 56 | extern bool G_USE_GYRO; 57 | 58 | extern bool G_IS_IPAD2; 59 | extern int G_NUM_PARTICLES; 60 | extern int G_NUM_DUSTS; -------------------------------------------------------------------------------- /src/HelpLayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * UiLayer.h 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 2/7/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "cinder/Vector.h" 13 | #include "cinder/gl/Texture.h" 14 | #include "cinder/Font.h" 15 | #include "cinder/Rect.h" 16 | #include "cinder/app/TouchEvent.h" 17 | #include "BloomNode.h" 18 | 19 | class HelpLayer : public BloomNode { 20 | public: 21 | 22 | HelpLayer() {}; 23 | ~HelpLayer() {}; 24 | 25 | void setup( const ci::Font &smallFont, const ci::Font &bigFont, const ci::Font &bigBoldFont ); 26 | 27 | bool touchBegan( ci::app::TouchEvent::Touch touch ); 28 | bool touchEnded( ci::app::TouchEvent::Touch touch ); 29 | 30 | void update(); 31 | void draw(); 32 | 33 | void show( bool show = true, bool animate = true ); 34 | void hide( bool animate = true ) { show( false, animate ); } 35 | void toggle() { show( !isShowing() ); } 36 | bool isShowing() { return mShowing; } 37 | 38 | float getHeight() { return mBgRect.getHeight() + mCurrentY; } 39 | 40 | private: 41 | 42 | void updateRect( ci::Rectf *rect, const std::wstring &fullStr, const std::wstring &rectStr, const std::vector > &glyphPositions ); 43 | 44 | // control visibility, animation 45 | bool mShowing, mAnimating; 46 | float mCurrentY, mTargetY; 47 | 48 | // fonts 49 | ci::Font mBigFont, mBigBoldFont, mSmallFont; 50 | 51 | // textures 52 | ci::gl::Texture mHeadingTex, mBodyTex; 53 | 54 | // dimensions and positions 55 | ci::Vec2f mInterfaceSize, mHeadingPos, mBodyPos; 56 | ci::Rectf mBgRect; 57 | 58 | // hit rects for links: 59 | ci::Rectf mCinderRect, mWebRect, mEmailRect; 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /xcode/Kepler-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleDocumentTypes 10 | 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleGetInfoString 14 | 15 | CFBundleIconFile 16 | Icon.png 17 | CFBundleIdentifier 18 | io.bloom.planetary 19 | CFBundleInfoDictionaryVersion 20 | 6.0 21 | CFBundleName 22 | ${PRODUCT_NAME} 23 | CFBundlePackageType 24 | APPL 25 | CFBundleShortVersionString 26 | 2.0.0 27 | CFBundleSignature 28 | ???? 29 | CFBundleURLTypes 30 | 31 | CFBundleVersion 32 | 2.0.0 33 | LSApplicationCategoryType 34 | 35 | LSRequiresIPhoneOS 36 | 37 | NSMainNibFile 38 | 39 | UIStatusBarHidden 40 | 41 | UISupportedInterfaceOrientations 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UTExportedTypeDeclarations 51 | 52 | UTImportedTypeDeclarations 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/Slider.h: -------------------------------------------------------------------------------- 1 | // 2 | // Slider.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/17/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include "BloomNode.h" 11 | #include "cinder/Area.h" 12 | #include "cinder/Rect.h" 13 | #include "cinder/gl/Texture.h" 14 | 15 | class Slider : public BloomNode { 16 | public: 17 | 18 | Slider(const int &id, 19 | const ci::gl::Texture &texture, 20 | const ci::Area &bgTexArea, 21 | const ci::Area &fgTexArea, 22 | const ci::Area &thumbDownTexArea, 23 | const ci::Area &thumbUpTexArea): 24 | BloomNode(id), 25 | mTexture(texture), 26 | // texture Areas: 27 | mBgTexArea(bgTexArea), 28 | mFgTexArea(fgTexArea), 29 | mThumbDownTexArea(thumbDownTexArea), 30 | mThumbUpTexArea(thumbUpTexArea), 31 | // state: 32 | mValue(0.0f), 33 | mIsDragging(false) {} 34 | 35 | ~Slider() {} 36 | 37 | bool isDragging(); 38 | void setIsDragging(bool isDragging); 39 | 40 | float getValue(); 41 | void setValue(float value); 42 | 43 | virtual bool touchBegan(ci::app::TouchEvent::Touch touch); 44 | virtual bool touchMoved(ci::app::TouchEvent::Touch touch); 45 | virtual bool touchEnded(ci::app::TouchEvent::Touch touch); 46 | virtual void draw(); 47 | 48 | void setRect(const ci::Rectf &rect) { mRect = rect; } 49 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 50 | const ci::Rectf& getRect() const { return mRect; } 51 | 52 | protected: 53 | 54 | ci::Area mFgTexArea, mBgTexArea, mThumbDownTexArea, mThumbUpTexArea; // texture coords, fixed 55 | ci::gl::Texture mTexture; 56 | ci::Rectf mRect; 57 | 58 | float mValue; 59 | bool mIsDragging; 60 | 61 | void updateVerts(); 62 | }; -------------------------------------------------------------------------------- /src/AlphaChooser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AlphaChooser.h 3 | * Kepler 4 | * 5 | * Created by Tom Carden on 3/14/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | #include "cinder/Vector.h" 12 | #include "cinder/gl/Texture.h" 13 | #include "cinder/Rect.h" 14 | #include "cinder/Color.h" 15 | #include "cinder/Font.h" 16 | #include "cinder/Function.h" 17 | 18 | #include "BloomNode.h" 19 | 20 | class AlphaChooser; 21 | typedef std::shared_ptr AlphaChooserRef; 22 | 23 | class AlphaChooser : public BloomNode { 24 | 25 | public: 26 | 27 | AlphaChooser(): mOpacity(1.0f) {}; 28 | ~AlphaChooser() {}; 29 | 30 | void setup( const ci::Font &font, const ci::Vec2f &interfaceSize ); 31 | void update(); 32 | void draw(); 33 | 34 | bool touchBegan( ci::app::TouchEvent::Touch touch ); 35 | bool touchMoved( ci::app::TouchEvent::Touch touch ); 36 | bool touchEnded( ci::app::TouchEvent::Touch touch ); 37 | 38 | void setNumberAlphaPerChar( float *numAlphaPerChar ); 39 | 40 | void setAlphaChar( char c ){ mAlphaChar = c; } 41 | char getAlphaChar(){ return mAlphaChar; } 42 | 43 | template 44 | ci::CallbackId registerAlphaCharSelected( T *obj, bool ( T::*callback )( char ) ){ 45 | return mCallbacksAlphaCharSelected.registerCb(std::bind1st( std::mem_fun( callback ), obj ) ); 46 | } 47 | 48 | bool hitTest( ci::Vec2f globalPos ) { return mVisible && mFullRect.contains( globalToLocal( globalPos ) ); } 49 | 50 | // used in UiLayer layout... 51 | float getHeight(); 52 | 53 | void setOpacity( float opacity ) { mOpacity = opacity; } 54 | 55 | private: 56 | 57 | void setRects(); 58 | 59 | float *mNumberAlphaPerChar; 60 | 61 | std::string mAlphaString; 62 | int mAlphaIndex; 63 | char mAlphaChar; 64 | 65 | float mOpacity; 66 | 67 | ci::Vec2f mInterfaceSize; 68 | 69 | std::vector mAlphaTextures; 70 | std::vector mAlphaRects; 71 | std::vector mAlphaHitRects; 72 | ci::Rectf mFullRect; 73 | 74 | ci::CallbackMgr mCallbacksAlphaCharSelected; 75 | }; 76 | 77 | -------------------------------------------------------------------------------- /src/TextureLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextureLoader.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 7/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include "cinder/Vector.h" 14 | #include "cinder/Surface.h" 15 | #include "cinder/gl/Texture.h" 16 | #include "cinder/Function.h" 17 | #include "cinder/Thread.h" 18 | 19 | class TextureLoader { 20 | public: 21 | 22 | TextureLoader() {} 23 | ~TextureLoader() {} 24 | 25 | int getTotal() { return mTotalRequests; } 26 | int getCount() { return mTextures.size(); } 27 | float getProgress() 28 | { 29 | float count = (float)getCount(); 30 | float total = (float)getTotal(); 31 | if (total > 0) return count / total; 32 | return 0; 33 | } 34 | 35 | void addRequest( int texId, std::string fileName ); 36 | void addRequest( int texId, std::string fileName, ci::gl::Texture::Format format ); 37 | // void addRequest( int texId, std::string compressedFileName, ci::Vec2i size ); 38 | 39 | ci::gl::Texture operator[](const int &index){ return mTextures[index]; }; 40 | 41 | template 42 | ci::CallbackId registerComplete( T *obj, void ( T::*callback )( TextureLoader* ) ){ 43 | return mCbComplete.registerCb(std::bind1st( std::mem_fun( callback ), obj ) ); 44 | } 45 | 46 | // begin the thread 47 | void start(); 48 | 49 | private: 50 | 51 | struct Request { 52 | int mTexId; 53 | std::string mFileName; 54 | ci::Surface mSurface; 55 | ci::gl::Texture::Format mFormat; 56 | 57 | Request( int texId, std::string fileName, ci::gl::Texture::Format format ): mTexId(texId), mFileName(fileName), mFormat(format) {} 58 | }; 59 | 60 | std::mutex mRequestsMutex; 61 | std::vector mRequests; 62 | int mTotalRequests; // mRequests.size() but threadsafe 63 | int mRequestsComplete; 64 | 65 | std::map mTextures; 66 | 67 | ci::CallbackMgr mCbComplete; 68 | 69 | void loadSurfaces(); // background thread 70 | void surfaceLoaded(); // ui thread 71 | 72 | }; -------------------------------------------------------------------------------- /src/Galaxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Galaxy.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/9/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "cinder/gl/gl.h" 12 | #include "cinder/gl/Texture.h" 13 | #include "cinder/Camera.h" 14 | 15 | class Galaxy { 16 | public: 17 | 18 | struct VertexData { 19 | ci::Vec3f vertex; 20 | ci::Vec2f texture; 21 | }; 22 | 23 | Galaxy() { 24 | mGalaxyVBO = 0; 25 | mDarkMatterVBO = 0; 26 | } 27 | 28 | ~Galaxy() { 29 | if (mDarkMatterVBO != 0) { 30 | glDeleteBuffers(1, &mDarkMatterVBO); 31 | } 32 | if (mGalaxyVBO != 0) { 33 | glDeleteBuffers(1, &mGalaxyVBO); 34 | } 35 | } 36 | 37 | void setup(float initialCamDist, 38 | ci::Color lightMatterColor, 39 | ci::Color centerColor, 40 | ci::gl::Texture galaxyDome, 41 | ci::gl::Texture galaxyTex, 42 | ci::gl::Texture darkMatterTex, 43 | ci::gl::Texture starGlowTex); 44 | 45 | void update(const ci::Vec3f &eye, 46 | const float &fadeInAlphaToArtist, 47 | const float rotSpeed, 48 | const float eclipseAmt, 49 | const ci::Vec3f &bbRight, 50 | const ci::Vec3f &bbUp); 51 | 52 | void drawLightMatter( float fadeInAlphaToArtist ); 53 | void drawSpiralPlanes(); 54 | void drawCenter(); 55 | void drawDarkMatter(); 56 | 57 | private: 58 | 59 | // set in update() 60 | float mZoomOff, mCamGalaxyAlpha, mInvAlpha, mElapsedSeconds; 61 | ci::Vec3f mBbRight, mBbUp; 62 | 63 | // set in setup() 64 | ci::gl::Texture mGalaxyDome, mGalaxyTex, mDarkMatterTex, mStarGlowTex; 65 | ci::Color mCenterColor, mLightMatterColor; 66 | 67 | // called in setup() 68 | void initGalaxyVertexArray(); 69 | void initDarkMatterVertexArray(); 70 | 71 | // set in initXXX(), used in drawXXX() 72 | GLuint mGalaxyVBO, mDarkMatterVBO; 73 | 74 | int mDarkMatterCylinderRes; 75 | float mLightMatterBaseRadius; 76 | float mDarkMatterBaseRadius; 77 | 78 | float mDistFromCamZAxis; 79 | }; 80 | -------------------------------------------------------------------------------- /src/NodeAlbum.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NodeAlbum.h 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 1/21/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "cinder/Vector.h" 13 | #include "Node.h" 14 | #include "OrbitRing.h" 15 | //#include "Shadow.h" 16 | 17 | class NodeAlbum : public Node 18 | { 19 | public: 20 | NodeAlbum( Node *parent, int index, const ci::Font &font, const ci::Font &smallFont, const ci::Surface &hiResSurfaces, const ci::Surface &loResSurfaces, const ci::Surface &noAlbumArt ); 21 | 22 | void setData( ci::ipod::PlaylistRef album ); 23 | void update( float param1, float param2 ); 24 | void drawEclipseGlow(); 25 | void drawPlanet( const ci::gl::Texture &tex ); 26 | void drawClouds( const std::vector< ci::gl::Texture> &clouds ); 27 | void drawRings( const ci::gl::Texture &tex, const PlanetRing &planetRing, float camZPos ); 28 | void drawAtmosphere( const ci::Vec3f &camEye, const ci::Vec2f ¢er, const ci::gl::Texture &tex, const ci::gl::Texture &directionalTex, float pinchAlphaPer, float scaleSliderOffset ); 29 | void drawOrbitRing( float pinchAlphaOffset, float camAlpha, const OrbitRing &orbitRing, float fadeInAlphaToArtist, float fadeInArtistToAlbum ); 30 | void findShadows( float camAlpha ); 31 | void buildShadowVertexArray( ci::Vec3f p1, ci::Vec3f p2, ci::Vec3f p3, ci::Vec3f p4 ); 32 | void select(); 33 | void setChildOrbitRadii(); 34 | string getName(); 35 | float getReleaseYear(); 36 | uint64_t getId(); 37 | 38 | ci::ipod::PlaylistRef getPlaylist() { return mAlbum; } 39 | 40 | // TODO: should this be private? 41 | int mNumTracks; 42 | ci::Surface mAlbumArtSurface; 43 | 44 | private: 45 | struct VertexData { 46 | ci::Vec2f vertex; 47 | ci::Vec2f texture; 48 | }; 49 | GLuint mAlbumArtVbo; 50 | 51 | float mReleaseYear; 52 | float mTotalLength; 53 | float mAsciiPer; 54 | bool mHasAlbumArt; 55 | bool mHasRings; 56 | bool mHasClouds; 57 | bool mIsBlockedBySun; 58 | float mBlockedBySunPer; 59 | ci::gl::Texture mAlbumArtTex; 60 | ci::ipod::PlaylistRef mAlbum; 61 | float mCloudLayerRadius; 62 | uint64_t mId; 63 | // Shadow mShadow; 64 | GLfloat *mShadowVerts; 65 | GLfloat *mShadowTexCoords; 66 | 67 | 68 | }; -------------------------------------------------------------------------------- /src/TimeLabel.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // TimeLabel.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "TimeLabel.h" 10 | #include "cinder/gl/gl.h" 11 | #include "cinder/Text.h" 12 | #include "BloomGl.h" 13 | 14 | void TimeLabel::setSeconds(int seconds) 15 | { 16 | if (mSeconds != seconds) { 17 | mSeconds = seconds; 18 | updateTexture(); 19 | } 20 | } 21 | 22 | void TimeLabel::updateTexture() 23 | { 24 | int hours = floor(abs(mSeconds)/3600.0f); 25 | int minutes = floor(abs(mSeconds)/60.0f); 26 | minutes = minutes - hours * 60; 27 | int seconds = (int)abs(mSeconds)%60; 28 | 29 | string hourStr = ci::toString( hours ); 30 | string minsStr = ci::toString( minutes ); 31 | string secsStr = ci::toString( seconds ); 32 | if( minsStr.length() == 1 ) minsStr = "0" + minsStr; 33 | if( secsStr.length() == 1 ) secsStr = "0" + secsStr; 34 | 35 | stringstream ss; 36 | if( hours > 0 ) 37 | ss << hourStr << ":"; 38 | ss << minsStr << ":" << secsStr << endl; 39 | 40 | TextLayout layout; 41 | layout.setFont( mFont ); 42 | layout.setColor( mColor ); 43 | layout.addLine( ss.str() ); 44 | mTexture = layout.render( true, false ); 45 | 46 | if (mSeconds <= 0) { 47 | TextLayout hyphenLayout; 48 | hyphenLayout.setFont( mFont ); 49 | hyphenLayout.setColor( mColor ); 50 | hyphenLayout.addLine( "-" ); 51 | mHyphenTexture = hyphenLayout.render( true, false ); 52 | } 53 | else { 54 | mHyphenTexture.reset(); 55 | } 56 | } 57 | 58 | void TimeLabel::draw() 59 | { 60 | // to keep the digit left-aligned in the box, squeeze the minus sign in before it 61 | if (mHyphenTexture) { 62 | bloom::gl::batchRect( mHyphenTexture, mRect.getUpperLeft() - Vec2f(mHyphenTexture.getWidth()-1.0f,0) ); 63 | } 64 | if (mTexture) { 65 | bloom::gl::batchRect( mTexture, mRect.getUpperLeft() ); 66 | } 67 | } 68 | 69 | bool TimeLabel::touchBegan(ci::app::TouchEvent::Touch touch) 70 | { 71 | return mRect.contains( globalToLocal( touch.getPos() ) ); 72 | } 73 | bool TimeLabel::touchEnded(ci::app::TouchEvent::Touch touch) 74 | { 75 | return mRect.contains( globalToLocal( touch.getPos() ) ); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/Buttons.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Buttons.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/17/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "Buttons.h" 10 | #include "cinder/gl/gl.h" 11 | #include "BloomGl.h" 12 | 13 | using namespace ci; 14 | 15 | void ToggleButton::draw() 16 | { 17 | Area textureArea = mOn ? mOnTextureArea : mOffTextureArea; 18 | bloom::gl::batchRect( mTexture, textureArea, mRect ); 19 | } 20 | 21 | bool ToggleButton::touchBegan(ci::app::TouchEvent::Touch touch) 22 | { 23 | return mRect.contains( globalToLocal( touch.getPos() ) ); 24 | } 25 | bool ToggleButton::touchEnded(ci::app::TouchEvent::Touch touch) 26 | { 27 | return mRect.contains( globalToLocal( touch.getPos() ) ); 28 | } 29 | 30 | void SimpleButton::draw() 31 | { 32 | Area textureArea = mDownCount ? mDownTextureArea : mUpTextureArea; 33 | bloom::gl::batchRect( mTexture, textureArea, mRect ); 34 | } 35 | bool SimpleButton::touchBegan(ci::app::TouchEvent::Touch touch) 36 | { 37 | bool inside = mRect.contains( globalToLocal( touch.getPos() ) ); 38 | if (inside) mDownCount++; 39 | return inside; 40 | } 41 | bool SimpleButton::touchEnded(ci::app::TouchEvent::Touch touch) 42 | { 43 | mDownCount--; 44 | return mRect.contains( globalToLocal( touch.getPos() ) ); 45 | } 46 | 47 | void TwoStateButton::draw() 48 | { 49 | Area textureArea = mOn ? (mDownCount > 0 ? mOnDownTextureArea : mOnUpTextureArea) : (mDownCount > 0 ? mOffDownTextureArea : mOffUpTextureArea) ; 50 | bloom::gl::batchRect( mTexture, textureArea, mRect ); 51 | } 52 | bool TwoStateButton::touchBegan(ci::app::TouchEvent::Touch touch) 53 | { 54 | bool inside = mRect.contains( globalToLocal( touch.getPos() ) ); 55 | if (inside) mDownCount++; 56 | return inside; 57 | } 58 | bool TwoStateButton::touchEnded(ci::app::TouchEvent::Touch touch) 59 | { 60 | mDownCount--; 61 | return mRect.contains( globalToLocal( touch.getPos() ) ); 62 | } 63 | 64 | 65 | void ThreeStateButton::draw() 66 | { 67 | Area textureArea = mState == 0 ? mFirstTextureArea : mState == 1 ? mSecondTextureArea : mThirdTextureArea; 68 | bloom::gl::batchRect( mTexture, textureArea, mRect ); 69 | } 70 | bool ThreeStateButton::touchBegan(ci::app::TouchEvent::Touch touch) 71 | { 72 | return mRect.contains( globalToLocal( touch.getPos() ) ); 73 | } 74 | bool ThreeStateButton::touchEnded(ci::app::TouchEvent::Touch touch) 75 | { 76 | return mRect.contains( globalToLocal( touch.getPos() ) ); 77 | } 78 | -------------------------------------------------------------------------------- /src/Slider.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Slider.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/17/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "Slider.h" 10 | #include "cinder/gl/gl.h" 11 | #include "BloomGl.h" 12 | 13 | using namespace ci; 14 | 15 | bool Slider::isDragging() 16 | { 17 | return mIsDragging; 18 | } 19 | void Slider::setIsDragging(bool isDragging) 20 | { 21 | mIsDragging = isDragging; 22 | } 23 | 24 | float Slider::getValue() 25 | { 26 | return mValue; 27 | } 28 | void Slider::setValue(float value) 29 | { 30 | mValue = value; 31 | } 32 | 33 | void Slider::draw() 34 | { 35 | const float thumbProgress = (mRect.x2-mRect.x1) * mValue; 36 | const float midY = (mRect.y1 + mRect.y2) / 2.0f; 37 | 38 | const float thumbWidth = 28.0f; 39 | const float thumbHeight = 28.0f; 40 | 41 | Rectf fgRect(mRect.x1, mRect.y1, mRect.x1 + thumbProgress, mRect.y2); 42 | Rectf thumbRect(mRect.x1 + thumbProgress - thumbWidth/2.0f, 43 | midY - thumbHeight/2.0, 44 | mRect.x1 + thumbProgress + thumbWidth/2.0f, 45 | midY + thumbHeight/2.0); 46 | 47 | Area thumbTexArea = mIsDragging ? mThumbDownTexArea : mThumbUpTexArea; 48 | 49 | bloom::gl::batchRect( mTexture, mBgTexArea, mRect ); 50 | bloom::gl::batchRect( mTexture, mFgTexArea, fgRect ); 51 | bloom::gl::batchRect( mTexture, thumbTexArea, thumbRect ); 52 | } 53 | 54 | bool Slider::touchBegan(ci::app::TouchEvent::Touch touch) 55 | { 56 | if (mIsDragging) { 57 | // slider can only handle one touch 58 | return false; 59 | } 60 | Vec2f touchPos = globalToLocal( touch.getPos() ); 61 | Rectf hitRect = Rectf( mRect.x1 - 10.0f, mRect.y1 - 3.0f, mRect.x2 + 10.0f, mRect.y2 + 3.0f ); 62 | bool inside = hitRect.contains( globalToLocal( touch.getPos() ) ); 63 | setIsDragging(inside); 64 | return inside; 65 | } 66 | bool Slider::touchMoved(ci::app::TouchEvent::Touch touch) 67 | { 68 | if (!mIsDragging) { 69 | // reject touchMoved if dragging was canceled 70 | return false; 71 | } 72 | 73 | // adjust for orientation and offset 74 | Vec2f pos = globalToLocal( touch.getPos() ); 75 | 76 | // FIXME: assumes slider is horizontal :) 77 | float sliderPer = (pos.x - mRect.x1) / (mRect.x2 - mRect.x1); 78 | if (sliderPer < 0.0f) 79 | sliderPer = 0.0f; 80 | else if (sliderPer > 1.0f) 81 | sliderPer = 1.0f; 82 | 83 | setValue( sliderPer ); 84 | 85 | return true; // always consume drags for slider 86 | } 87 | bool Slider::touchEnded(ci::app::TouchEvent::Touch touch) 88 | { 89 | if (!mIsDragging) { 90 | // reject touchEnded if dragging was canceled 91 | return false; 92 | } 93 | touchMoved(touch); 94 | setIsDragging(false); 95 | return true; 96 | } 97 | -------------------------------------------------------------------------------- /src/Constellation.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Constellation.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/14/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "Constellation.h" 10 | #include "cinder/gl/gl.h" 11 | #include "Globals.h" 12 | 13 | using std::vector; 14 | using namespace ci; 15 | 16 | void Constellation::setup(const vector &filteredNodes) 17 | { 18 | mConstellation.clear(); 19 | //mConstellationColors.clear(); 20 | 21 | // CREATE DATA FOR CONSTELLATION 22 | vector distances; // used for tex coords of the dotted line 23 | for( vector::const_iterator it1 = filteredNodes.begin(); it1 != filteredNodes.end(); ++it1 ){ 24 | 25 | NodeArtist *child1 = *it1; 26 | float shortestDist = 5000.0f; 27 | NodeArtist *nearestChild; 28 | 29 | vector::const_iterator it2 = it1; 30 | for( ++it2; it2 != filteredNodes.end(); ++it2 ) { 31 | NodeArtist *child2 = *it2; 32 | 33 | Vec3f dirBetweenChildren = child1->mPosDest - child2->mPosDest; 34 | float distBetweenChildren = dirBetweenChildren.length(); 35 | if( distBetweenChildren < shortestDist ){ 36 | shortestDist = distBetweenChildren; 37 | nearestChild = child2; 38 | } 39 | } 40 | 41 | distances.push_back( shortestDist ); 42 | mConstellation.push_back( child1->mPosDest ); 43 | mConstellation.push_back( nearestChild->mPosDest ); 44 | } 45 | 46 | mTotalConstellationVertices = mConstellation.size(); 47 | if (mTotalConstellationVertices != mPrevTotalConstellationVertices) { 48 | if (mConstellationVerts != NULL) 49 | delete[] mConstellationVerts; 50 | mConstellationVerts = new VertexData[mTotalConstellationVertices]; 51 | mPrevTotalConstellationVertices = mTotalConstellationVertices; 52 | } 53 | 54 | int vIndex = 0; 55 | int distancesIndex = 0; 56 | for( int i=0; i 2 ){ 72 | 73 | gl::color( ColorA( 0.12f, 0.25f, 0.85f, alpha ) ); 74 | 75 | glEnableClientState( GL_VERTEX_ARRAY ); 76 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 77 | 78 | glVertexPointer( 3, GL_FLOAT, sizeof(VertexData), mConstellationVerts ); 79 | glTexCoordPointer( 2, GL_FLOAT, sizeof(VertexData), &mConstellationVerts[0].texture ); 80 | 81 | glDrawArrays( GL_LINES, 0, mTotalConstellationVertices ); 82 | 83 | glDisableClientState( GL_VERTEX_ARRAY ); 84 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 85 | } 86 | } -------------------------------------------------------------------------------- /src/Data.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Data.cpp 3 | * Kepler 4 | * 5 | * Created by Robert Hodgin on 2/25/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #include "Data.h" 11 | #include "cinder/Utilities.h" // for toString 12 | #include "CinderFlurry.h" // for loggin 13 | #include "TaskQueue.h" // for backgrounding tasks 14 | 15 | using namespace ci; 16 | using namespace ci::ipod; 17 | using namespace std; 18 | using namespace pollen::flurry; 19 | 20 | void Data::setup() 21 | { 22 | mArtists.clear(); 23 | mPlaylists.clear(); 24 | mNumArtistsPerChar.clear(); 25 | 26 | if (mState != LoadStateLoading) { 27 | mState = LoadStateLoading; 28 | mArtistProgress = 0.0f; 29 | mPlaylistProgress = 0.0f; 30 | TaskQueue::pushTask( std::bind( std::mem_fun( &Data::backgroundInit ), this ) ); 31 | } 32 | } 33 | 34 | void Data::backgroundInit() 35 | { 36 | Flurry::getInstrumentation()->startTimeEvent("Music Loading"); 37 | 38 | mPendingArtists = getArtists( std::bind1st( std::mem_fun(&Data::artistProgress), this ) ); 39 | mPendingPlaylists = getPlaylists( std::bind1st( std::mem_fun(&Data::playlistProgress), this ) ); 40 | 41 | map params; 42 | params["NumArtists"] = toString( mPendingArtists.size() ); 43 | params["NumPlaylists"] = toString( mPendingPlaylists.size() ); 44 | Flurry::getInstrumentation()->stopTimeEvent("Music Loading", params); 45 | 46 | // QUICK FIX FOR GETTING MORE DATA ONTO THE ALPHAWHEEL 47 | 48 | string alphaString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ#"; 49 | for( int i=0; i<27; i++ ){ 50 | mNumArtistsPerChar[alphaString[i]] = 0; 51 | } 52 | float maxCount = 0.0001f; 53 | for( vector::iterator it = mPendingArtists.begin(); it != mPendingArtists.end(); ++it ){ 54 | 55 | string name = (*it)->getArtistName(); 56 | string the = name.substr( 0, 4 ); 57 | char firstLetter; 58 | 59 | if( the == "The " || the == "the " ){ 60 | firstLetter = name[4]; 61 | } else { 62 | firstLetter = name[0]; 63 | } 64 | 65 | if( isdigit(firstLetter) ){ 66 | firstLetter = '#'; 67 | } else { 68 | firstLetter = static_cast ( toupper( firstLetter ) ); 69 | } 70 | 71 | mNumArtistsPerChar[firstLetter] += 1.0f; 72 | 73 | if( mNumArtistsPerChar[firstLetter] > maxCount ){ 74 | maxCount = mNumArtistsPerChar[firstLetter]; 75 | } 76 | } 77 | 78 | for( int i=0; i<27; i++ ){ 79 | mNormalizedArtistsPerChar[i] = mNumArtistsPerChar[alphaString[i]]/maxCount; 80 | } 81 | 82 | // END ALPHAWHEEL QUICK FIX 83 | 84 | mState = LoadStatePending; 85 | } 86 | 87 | 88 | void Data::update() 89 | { 90 | if (mState == LoadStatePending) { 91 | 92 | mArtists.insert( mArtists.end(), mPendingArtists.begin(), mPendingArtists.end() ); 93 | mPendingArtists.clear(); 94 | 95 | mPlaylists.insert( mPlaylists.end(), mPendingPlaylists.begin(), mPendingPlaylists.end() ); 96 | mPendingPlaylists.clear(); 97 | 98 | mState = LoadStateComplete; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/OrbitRing.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Rings.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/13/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "cinder/gl/gl.h" 10 | #include "cinder/Color.h" 11 | #include "OrbitRing.h" 12 | #include "Globals.h" 13 | 14 | using namespace ci; 15 | 16 | OrbitRing::OrbitRing() 17 | { 18 | mLowResVBO = 0; 19 | mHighResVBO = 0; 20 | } 21 | 22 | OrbitRing::~OrbitRing() 23 | { 24 | if (mLowResVBO != 0) { 25 | glDeleteBuffers(1, &mLowResVBO); 26 | } 27 | if (mHighResVBO != 0) { 28 | glDeleteBuffers(1, &mHighResVBO); 29 | } 30 | } 31 | 32 | void OrbitRing::setup() 33 | { 34 | VertexData *mVertsLowRes = new VertexData[ G_RING_LOW_RES ]; // X,Y,U,V 35 | 36 | for( int i=0; i 12 | #include 13 | 14 | #include "cinder/app/AppCocoaTouch.h" 15 | #include "cinder/gl/TextureFont.h" 16 | #include "cinder/Font.h" 17 | #include "cinder/Color.h" 18 | #include "cinder/Camera.h" 19 | 20 | #include "CinderIPod.h" 21 | 22 | #include "Data.h" 23 | #include "World.h" 24 | #include "BloomNode.h" 25 | 26 | class PlaylistChooser; 27 | typedef std::shared_ptr PlaylistChooserRef; 28 | 29 | typedef std::shared_ptr RectRef; 30 | 31 | class PlaylistChooser : public BloomNode { 32 | 33 | public: 34 | 35 | PlaylistChooser(): mData(NULL), mOffsetX(0.0f), mOpacity(1.0f) {} 36 | 37 | void setup( const ci::Font &font, const ci::Vec2f &interfaceSize ); 38 | void update(); 39 | void draw(); 40 | 41 | bool touchBegan( ci::app::TouchEvent::Touch touch ); 42 | bool touchMoved( ci::app::TouchEvent::Touch touch ); 43 | bool touchEnded( ci::app::TouchEvent::Touch touch ); 44 | 45 | void setDataWorldCam(Data *data, World *world, ci::CameraPersp *cam); 46 | 47 | template 48 | ci::CallbackId registerPlaylistSelected( T *obj, bool ( T::*callback )( ci::ipod::PlaylistRef ) ){ 49 | return mCbPlaylistSelected.registerCb(std::bind1st( std::mem_fun( callback ), obj ) ); 50 | } 51 | 52 | template 53 | ci::CallbackId registerPlaylistTouched( T *obj, bool ( T::*callback )( ci::ipod::PlaylistRef ) ){ 54 | return mCbPlaylistTouched.registerCb(std::bind1st( std::mem_fun( callback ), obj ) ); 55 | } 56 | 57 | bool hitTest( ci::Vec2f globalPos ) { return mVisible && mFullRect.contains( globalToLocal( globalPos ) ); } 58 | 59 | // used in UiLayer layout... 60 | float getHeight(); 61 | 62 | void setOpacity( float opacity ) { mOpacity = opacity; } 63 | 64 | void clearTextures() { mTextures.clear(); } 65 | 66 | private: 67 | 68 | float getAlpha( float x ); 69 | void makeTexture( int index, ci::ipod::PlaylistRef playlist ); 70 | 71 | int mNumPlaylists; 72 | int mCurrentIndex; 73 | int mPrevIndex; 74 | 75 | ci::Vec2i mTouchPos, mTouchPrevPos; 76 | float mTouchVel; 77 | uint64_t mTouchDragId; 78 | ci::Vec2f mTouchDragStartPos; 79 | float mTouchDragStartOffset; 80 | int mTouchDragPlaylistIndex; 81 | bool mIsDragging; 82 | 83 | ci::Vec2f mPlaylistSize; 84 | float mSpacerWidth; 85 | float mOffsetX; // for scrolling 86 | float mStartY; 87 | 88 | float mOpacity; 89 | 90 | ci::Rectf mFullRect; 91 | 92 | std::vector mPlaylistRects; 93 | 94 | std::vector mTextures; 95 | 96 | Data *mData; // for playlists 97 | World *mWorld; // for nodes 98 | ci::CameraPersp *mCam; // for projecting to screen 99 | 100 | ci::Font mFont; 101 | float mFontHeight; 102 | 103 | ci::Vec2f mInterfaceSize; 104 | 105 | ci::CallbackMgr mCbPlaylistSelected, mCbPlaylistTouched; 106 | }; -------------------------------------------------------------------------------- /src/UiLayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * UiLayer.h 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 2/7/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | #include 12 | #include "cinder/Vector.h" 13 | #include "cinder/gl/Texture.h" 14 | #include "cinder/Rect.h" 15 | #include "cinder/Color.h" 16 | #include "cinder/Font.h" 17 | #include "BloomNode.h" 18 | #include "PlaylistChooser.h" 19 | #include "AlphaChooser.h" 20 | #include "PlayControls.h" 21 | #include "SettingsPanel.h" 22 | 23 | class UiLayer : public BloomNode { 24 | public: 25 | 26 | UiLayer(): 27 | BloomNode(), // get a default ID 28 | mChooserY(0.0f), 29 | mSettingsY(0.0f), 30 | mChooserDestY(0.0f), 31 | mSettingsDestY(0.0f) 32 | { }; 33 | 34 | ~UiLayer() {}; 35 | 36 | void setup( PlaylistChooserRef playlistChooser, 37 | AlphaChooserRef alphaChooser, 38 | PlayControlsRef playControls, 39 | SettingsPanelRef settingsPanel, 40 | const ci::gl::Texture &uiButtonsTex, 41 | const bool &showSettings, 42 | const ci::Vec2f interfaceSize ); 43 | 44 | bool touchBegan( ci::app::TouchEvent::Touch touch ); 45 | bool touchMoved( ci::app::TouchEvent::Touch touch ); 46 | bool touchEnded( ci::app::TouchEvent::Touch touch ); 47 | 48 | void setShowSettings( bool visible ); 49 | 50 | void update(); 51 | void draw(); 52 | 53 | float getPanelYPos(){ return mPanelY; } 54 | 55 | bool getIsPanelOpen() { return mIsPanelOpen; } 56 | void setIsPanelOpen( bool b ){ mIsPanelOpen = b; mHasPanelBeenDragged = false; } 57 | 58 | bool hitTest( ci::Vec2f globalPos ); 59 | 60 | //// expand/collapse/query panels 61 | void setShowAlphaFilter(bool visible); 62 | bool isShowingAlphaFilter(); 63 | void setShowPlaylistFilter(bool visible); 64 | bool isShowingPlaylistFilter(); 65 | bool isShowingFilter(); 66 | 67 | private: 68 | 69 | void updateLayout( ci::Vec2f interfaceSize ); 70 | 71 | ci::Vec2f mInterfaceSize; // for detecting orientation changes 72 | ci::gl::Texture mButtonsTex; 73 | 74 | float mPanelY; // used in setTransform 75 | float mPanelOpenY; // updated in setShowSettings/updateLayout 76 | float mPanelClosedY; // updated in updateLayout 77 | ci::Rectf mPanelTabRect; // Rect defining the panel tab 78 | 79 | bool mIsPanelTabTouched; // Is the Panel Tab currently being touched 80 | bool mIsPanelOpen; // Is the Panel fully open 81 | bool mHasPanelBeenDragged; // Are we dragging or just animating? 82 | ci::Vec2f mPanelTabTouchOffset; // Remember the touch position value when dragging 83 | 84 | float getPanelHeight(); 85 | float getMaxPanelHeight(); 86 | 87 | float mChooserY, mSettingsY; 88 | float mChooserDestY, mSettingsDestY; 89 | 90 | PlaylistChooserRef mPlaylistChooser; 91 | AlphaChooserRef mAlphaChooser; 92 | PlayControlsRef mPlayControls; 93 | SettingsPanelRef mSettingsPanel; 94 | }; 95 | 96 | typedef std::shared_ptr UiLayerRef; 97 | 98 | -------------------------------------------------------------------------------- /src/State.h: -------------------------------------------------------------------------------- 1 | /* 2 | * State.h 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 2/7/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | #include "cinder/app/AppCocoaTouch.h" 12 | #include "cinder/Vector.h" 13 | #include "cinder/Font.h" 14 | #include "cinder/gl/gl.h" 15 | #include "cinder/gl/Texture.h" 16 | #include "Globals.h" 17 | #include "Node.h" 18 | #include "NodeTrack.h" 19 | 20 | using namespace ci; 21 | 22 | class State { 23 | public: 24 | 25 | enum FilterMode { 26 | FilterModeAlphaChar, 27 | FilterModePlaylist 28 | }; 29 | 30 | State() {}; 31 | 32 | void setup(); 33 | 34 | // Alpha char for filtering artist name 35 | char getAlphaChar(){ return mAlphaChar; } 36 | void setAlphaChar( char c ); 37 | void setAlphaChar( const string &artistName ); 38 | template 39 | CallbackId registerAlphaCharStateChanged( T *obj, bool ( T::*callback )( char ) ){ 40 | return mCallbacksAlphaCharStateChanged.registerCb(std::bind1st( std::mem_fun( callback ), obj ) ); 41 | } 42 | 43 | 44 | // Playlist filtering 45 | ci::ipod::PlaylistRef getPlaylist(){ return mCurrentPlaylist; } 46 | void setPlaylist( ci::ipod::PlaylistRef playlist ); 47 | template 48 | CallbackId registerPlaylistStateChanged( T *obj, bool ( T::*callback )( ci::ipod::PlaylistRef ) ){ 49 | return mCallbacksPlaylistStateChanged.registerCb(std::bind1st( std::mem_fun( callback ), obj ) ); 50 | } 51 | 52 | 53 | Node* getSelectedNode() { return mSelectedNode; } 54 | void setSelectedNode( Node* selectedNode ); 55 | float getDistBetweenNodes() { return mDistBetweenPrevAndCurrentNode; } 56 | 57 | template 58 | CallbackId registerNodeSelected( T *obj, bool (T::*callback)(Node*) ){ 59 | return mCallbacksNodeSelected.registerCb(std::bind1st(std::mem_fun(callback), obj)); 60 | } 61 | 62 | // TODO: should these use casts to get NodeArtist/NodeAlbum out? 63 | Node* getSelectedArtistNode() { return getNodeAtLevel(G_ARTIST_LEVEL); } 64 | Node* getSelectedAlbumNode() { return getNodeAtLevel(G_ALBUM_LEVEL); } 65 | Node* getSelectedTrackNode() { return getNodeAtLevel(G_TRACK_LEVEL); } 66 | Node* getNodeAtLevel(int level) { 67 | if ( mSelectedNode != NULL && mSelectedNode->mGen >= level ) { 68 | Node *retNode = mSelectedNode; 69 | while ( retNode->mGen != level) { 70 | retNode = retNode->mParentNode; 71 | } 72 | return retNode; 73 | } 74 | return NULL; 75 | } 76 | 77 | bool setFilterMode(FilterMode filterMode); 78 | FilterMode getFilterMode() { return mFilterMode; } 79 | template 80 | CallbackId registerFilterModeStateChanged( T *obj, bool ( T::*callback )( FilterMode ) ){ 81 | return mCallbacksFilterModeStateChanged.registerCb(std::bind1st( std::mem_fun( callback ), obj ) ); 82 | } 83 | 84 | private: 85 | CallbackMgr mCallbacksPlaylistStateChanged; 86 | CallbackMgr mCallbacksAlphaCharStateChanged; 87 | CallbackMgr mCallbacksFilterModeStateChanged; 88 | CallbackMgr mCallbacksNodeSelected; 89 | CallbackMgr mCallbacksNodePlaying; 90 | 91 | Node *mSelectedNode; 92 | float mDistBetweenPrevAndCurrentNode; // used to control duration of the tween 93 | 94 | FilterMode mFilterMode; 95 | char mAlphaChar; 96 | ci::ipod::PlaylistRef mCurrentPlaylist; 97 | }; 98 | 99 | -------------------------------------------------------------------------------- /src/ScrollingLabel.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollingLabel.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "ScrollingLabel.h" 10 | #include "cinder/app/AppCocoaTouch.h" // app::getElapsedSeconds() 11 | #include "cinder/gl/gl.h" 12 | #include "cinder/Text.h" 13 | #include "BloomGl.h" 14 | 15 | using namespace std; 16 | using namespace ci; 17 | using namespace ci::app; 18 | 19 | void ScrollingLabel::setText(string text) 20 | { 21 | if (mText != text) { 22 | mIsScrolling = false; 23 | mText = text; 24 | updateTexture(); 25 | mLastChangeTime = app::getElapsedSeconds(); 26 | } 27 | } 28 | 29 | void ScrollingLabel::updateTexture() 30 | { 31 | if (mText == "") { 32 | mTexture.reset(); 33 | } 34 | else { 35 | TextLayout layout; 36 | layout.setFont( mFont ); 37 | layout.setColor( mColor ); 38 | layout.addLine( mText ); 39 | bool PREMULT = false; 40 | mTexture = gl::Texture( layout.render( true, PREMULT ) ); 41 | } 42 | } 43 | 44 | void ScrollingLabel::update() 45 | { 46 | if (mTexture) { 47 | 48 | float ctSpaceWidth = mRect.x2 - mRect.x1; 49 | float ctTexWidth = mTexture.getWidth(); 50 | 51 | if( ctTexWidth < ctSpaceWidth ){ 52 | mIsScrolling = false; 53 | } 54 | else { 55 | // if the texture is too wide, animate the u coords... 56 | float elapsedSeconds = ci::app::getElapsedSeconds(); 57 | float x1; 58 | if( elapsedSeconds - mLastChangeTime > 5.0f ) { 59 | // but wait 5 seconds first 60 | mIsScrolling = true; 61 | x1 = fmodf( ( elapsedSeconds - ( mLastChangeTime + 5.0f ) ) * 20.0f, ctTexWidth + 10.0f ) - ctTexWidth-10.0f; 62 | } else { 63 | x1 = -ctTexWidth-10.0f; 64 | } 65 | 66 | mFirstArea = Area( x1, 0.0f, x1 + ctSpaceWidth, mTexture.getHeight() ); 67 | mSecondArea = Area( x1 + ctTexWidth + 10.0f, 0.0f, x1 + ctTexWidth + 10.0f + ctSpaceWidth, mTexture.getHeight() ); 68 | } 69 | } 70 | } 71 | 72 | void ScrollingLabel::draw() 73 | { 74 | if (mTexture) { 75 | 76 | // force texture height to be correct: 77 | float restoreY2 = mRect.y2; 78 | mRect.y2 = mRect.y1 + mTexture.getHeight(); 79 | 80 | float ctSpaceWidth = mRect.x2 - mRect.x1; 81 | float ctTexWidth = mTexture.getWidth(); 82 | 83 | if( ctTexWidth < ctSpaceWidth ){ 84 | // if the texture width is less than the rect to fit it in... 85 | bloom::gl::batchRect( mTexture, mRect.getUpperLeft() ); 86 | } 87 | else { 88 | bloom::gl::batchRect( mTexture, mFirstArea, mRect ); 89 | bloom::gl::batchRect( mTexture, mSecondArea, mRect ); 90 | } 91 | 92 | // restore mRect 93 | // (this is a hack because mRect is also used for hit testing) 94 | mRect.y2 = restoreY2; 95 | } 96 | } 97 | 98 | bool ScrollingLabel::touchBegan( TouchEvent::Touch touch ) 99 | { 100 | return mRect.contains( globalToLocal( touch.getPos() ) ); 101 | } 102 | 103 | bool ScrollingLabel::touchEnded( TouchEvent::Touch touch ) 104 | { 105 | return mRect.contains( globalToLocal( touch.getPos() ) ); 106 | } 107 | -------------------------------------------------------------------------------- /src/State.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * State.cpp 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 2/7/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #include 11 | #include "State.h" 12 | #include "cinder/gl/gl.h" 13 | #include "cinder/Rect.h" 14 | 15 | using std::stringstream; 16 | using namespace ci; 17 | using namespace ci::app; 18 | using namespace std; 19 | 20 | void State::setup() 21 | { 22 | mFilterMode = FilterModeAlphaChar; 23 | mAlphaChar = 'A'; 24 | mSelectedNode = NULL; 25 | mDistBetweenPrevAndCurrentNode = 50.0f; 26 | } 27 | 28 | void State::setAlphaChar( char c ) 29 | { 30 | mAlphaChar = c; 31 | mCallbacksAlphaCharStateChanged.call( mAlphaChar ); 32 | } 33 | 34 | void State::setAlphaChar( const string &name ) 35 | { 36 | char firstLetter = name[0]; 37 | if (name.size() > 4) { 38 | string the = name.substr( 0, 4 ); 39 | if( the == "The " || the == "the " ){ 40 | firstLetter = name[4]; 41 | } 42 | } 43 | if (!isalpha(firstLetter)) { 44 | firstLetter = '#'; 45 | } 46 | setAlphaChar(firstLetter); 47 | } 48 | 49 | 50 | void State::setPlaylist( ci::ipod::PlaylistRef playlist ) 51 | { 52 | mCurrentPlaylist = playlist; 53 | mCallbacksPlaylistStateChanged.call( playlist ); 54 | } 55 | 56 | 57 | void State::setSelectedNode( Node* node ) 58 | { 59 | // if (node == mSelectedNode) { 60 | // return; 61 | // } 62 | 63 | if (node == NULL) { 64 | // clear currently selected node and all parents 65 | Node *selection = mSelectedNode; 66 | while( selection != NULL ) { 67 | selection->deselect(); 68 | selection = selection->mParentNode; 69 | } 70 | mSelectedNode = NULL; 71 | mDistBetweenPrevAndCurrentNode = 10.0f; 72 | } 73 | else { 74 | 75 | // deque so we can push_front instead of messing with reverse() 76 | deque currentChain; 77 | deque nextChain; 78 | 79 | Node* current = mSelectedNode; // track, album, artist 80 | while (current != NULL) { 81 | currentChain.push_front(current); 82 | current = current->mParentNode; 83 | } 84 | 85 | Node* next = node; // new track, album, artist 86 | while (next != NULL) { 87 | nextChain.push_front(next); 88 | next = next->mParentNode; 89 | } 90 | 91 | vector sharedAncestor; 92 | for (int i = 0; i < currentChain.size(); i++) { 93 | if (nextChain.size() - 1 < i) { 94 | sharedAncestor.push_back(false); 95 | } 96 | else { 97 | sharedAncestor.push_back(currentChain[i] == nextChain[i]); 98 | } 99 | } 100 | 101 | for (int i = currentChain.size() - 1; i >= 0; i--) { 102 | if (!sharedAncestor[i]) { 103 | currentChain[i]->deselect(); 104 | } 105 | } 106 | 107 | Node* prevSelectedNode = mSelectedNode; 108 | mSelectedNode = node; 109 | 110 | if( prevSelectedNode && mSelectedNode && (prevSelectedNode != mSelectedNode) ) { 111 | mDistBetweenPrevAndCurrentNode = prevSelectedNode->mPos.distance( mSelectedNode->mPos ); 112 | } 113 | 114 | // ensure everything in the next chain is selected 115 | for (int i = 0; i < nextChain.size(); i++) { 116 | nextChain[i]->select(); 117 | } 118 | } 119 | 120 | // and then spread the good word 121 | mCallbacksNodeSelected.call(mSelectedNode); 122 | } 123 | 124 | bool State::setFilterMode(FilterMode filterMode) 125 | { 126 | mFilterMode = filterMode; 127 | mCallbacksFilterModeStateChanged.call(filterMode); 128 | return false; // for use in callbacks 129 | } 130 | -------------------------------------------------------------------------------- /src/NodeTrack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NodeTrack.h 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 1/21/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "Node.h" 13 | #include "CinderIPod.h" 14 | #include "TaskQueue.h" 15 | 16 | class NodeTrack : public Node 17 | { 18 | public: 19 | NodeTrack( Node *parent, int index, const ci::Font &font, const ci::Font &smallFont, const ci::Surface &hiResSurfaces, const ci::Surface &loResSurfaces, const ci::Surface &noAlbumArt ); 20 | 21 | ~NodeTrack() 22 | { 23 | if (!UiTaskQueue::isTaskComplete(mTaskId)){ 24 | // cancel the album art rendering... 25 | UiTaskQueue::cancelTask(mTaskId); 26 | } 27 | } 28 | 29 | void setData( ci::ipod::TrackRef track, ci::ipod::PlaylistRef album, const ci::Surface &albumArt ); 30 | void initVertexArray(); 31 | void updateAudioData( double currentPlayheadTime ); 32 | void update( float param1, float param2 ); 33 | void drawEclipseGlow(); 34 | void drawPlanet( const ci::gl::Texture &tex ); 35 | void drawClouds( const std::vector< ci::gl::Texture> &clouds ); 36 | void drawOrbitRing( float pinchAlphaOffset, float camAlpha, const OrbitRing &orbitRing, float fadeInAlphaToArtist, float fadeInArtistToAlbum ); 37 | void buildPlayheadProgressVertexArray(); 38 | void drawPlayheadProgress( float pinchAlphaPer, float camAlpha, float pauseAlpha, const ci::gl::Texture &tex, const ci::gl::Texture &originTex ); 39 | // void drawAtmosphere( const ci::Vec2f ¢er, const ci::gl::Texture &tex, const ci::gl::Texture &directionalTex, float pinchAlphaPer ); 40 | void drawAtmosphere( const ci::Vec3f &camEye, const ci::Vec2f ¢er, const ci::gl::Texture &tex, const ci::gl::Texture &directionalTex, float pinchAlphaPer, float scaleSliderOffset ); 41 | void findShadows( float camAlpha ); 42 | void buildShadowVertexArray( ci::Vec3f p1, ci::Vec3f p2, ci::Vec3f p3, ci::Vec3f p4 ); 43 | 44 | ci::Vec3f getStartRelPos(){ return mStartRelPos; } 45 | ci::Vec3f getRelPos(){ return mRelPos; } 46 | 47 | void setStartAngle(); 48 | int getTrackNumber(); 49 | 50 | string getName(); 51 | uint64_t getId(); 52 | bool isMostPlayed() { return mIsMostPlayed; } 53 | 54 | // FIXME: should this be from a getData() function? or private? 55 | ci::ipod::TrackRef mTrack; 56 | ci::ipod::PlaylistRef mAlbum; 57 | 58 | private: 59 | float mShadowPer; 60 | 61 | float mAsciiPer; 62 | float mEclipseStrength; 63 | float mTrackLength; 64 | int mPlayCount; 65 | float mNormPlayCount; 66 | int mStarRating; 67 | int mNumTracks; 68 | ci::Vec3f mStartPos, mTransStartPos, mStartRelPos; 69 | vector mOrbitPath; 70 | 71 | float mPrevTime, mCurrentTime, mMyTime; 72 | double mStartTime; 73 | double mPlaybackTime; 74 | double mPercentPlayed; 75 | 76 | float mInitAngle; 77 | 78 | bool mHasClouds; 79 | bool mIsMostPlayed; 80 | bool mHasAlbumArt; 81 | bool mHasRequestedAlbumArt; 82 | ci::gl::Texture mAlbumArtTex; 83 | ci::Surface mAlbumArtSurface; 84 | 85 | float mCloudLayerRadius; 86 | 87 | // TODO: VBO or object: 88 | int mTotalOrbitVertices; 89 | int mPrevTotalOrbitVertices; 90 | GLfloat *mOrbitVerts; 91 | GLfloat *mOrbitTexCoords; 92 | GLfloat *mOrbitColors; 93 | 94 | // TODO: VBO or object 95 | GLfloat *mShadowVerts; 96 | GLfloat *mShadowTexCoords; 97 | 98 | uint64_t mId; 99 | 100 | void createAlbumArt(); // on ui thread please! 101 | uint64_t mTaskId; 102 | }; -------------------------------------------------------------------------------- /src/Vignette.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Vignette.cpp 3 | // Kepler 4 | // 5 | // Created by Robert Hodgin on 7/20/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "Vignette.h" 10 | 11 | #include 12 | 13 | #include "cinder/gl/gl.h" 14 | #include "cinder/Font.h" 15 | #include "cinder/Text.h" 16 | #include "cinder/ImageIo.h" 17 | 18 | #include "Globals.h" 19 | #include "BloomGl.h" 20 | #include "BloomScene.h" 21 | 22 | using std::stringstream; 23 | using namespace ci; 24 | using namespace ci::app; 25 | using namespace std; 26 | 27 | void Vignette::setup( const gl::Texture &tex ) 28 | { 29 | mScale = 2.25f; 30 | mShowing = false; 31 | mTex = tex; 32 | updateVerts(); 33 | } 34 | 35 | void Vignette::update() 36 | { 37 | float prevScale = mScale; 38 | 39 | if( mShowing ){ 40 | mScale -= ( mScale - 1.0f ) * 0.2f; 41 | } else { 42 | mScale -= ( mScale - 2.25f ) * 0.2f; 43 | } 44 | 45 | const Vec2f interfaceSize = getRoot()->getInterfaceSize(); 46 | 47 | if (mInterfaceSize != interfaceSize || mScale != prevScale) { 48 | 49 | mInterfaceSize = interfaceSize; 50 | mInterfaceCenter = mInterfaceSize * 0.5f; 51 | 52 | Matrix44f mat; 53 | mat.translate( Vec3f(mInterfaceCenter, 0) ); 54 | 55 | if ( mInterfaceSize.x > mInterfaceSize.y ) { 56 | // adjust for control panel in landscape 57 | float amount = (mInterfaceSize.x - mInterfaceSize.y) / (1024-768); 58 | mat.translate( Vec3f(0, -15.0f * amount, 0) ); 59 | } 60 | 61 | mat.scale( Vec3f( mScale, mScale, 1.0f ) ); 62 | setTransform(mat); 63 | } 64 | } 65 | 66 | void Vignette::updateVerts() 67 | { 68 | mTotalVertices = 6; 69 | 70 | mVerts = new VertexData[mTotalVertices]; 71 | 72 | float W = 1280; // sqrt(1024 * 1024 + 768 * 768) (diagonal) 73 | float H = W; // squared off for orientation animation 74 | float CW = W/2; 75 | float CH = H/2; 76 | 77 | vector positions; 78 | positions.push_back( Vec2i( 0 - CW, 0 - CH ) ); 79 | positions.push_back( Vec2i( W - CW, 0 - CH ) ); 80 | positions.push_back( Vec2i( 0 - CW, H - CH ) ); 81 | positions.push_back( Vec2i( W - CW, H - CH ) ); 82 | 83 | vector textures; 84 | textures.push_back( Vec2f( 0, 0 ) ); 85 | textures.push_back( Vec2f( 1, 0 ) ); 86 | textures.push_back( Vec2f( 0, 1 ) ); 87 | textures.push_back( Vec2f( 1, 1 ) ); 88 | 89 | int indices[6] = { 0, 1, 2, 1, 3, 2 }; 90 | 91 | // FIXME: just use an indexed VBO for this now it's static 92 | 93 | int vIndex = 0; 94 | for( int i = 0; i < mTotalVertices; i++ ){ 95 | mVerts[vIndex].vertex = positions[indices[i]]; 96 | mVerts[vIndex].texture = textures[indices[i]]; 97 | vIndex++; 98 | } 99 | } 100 | 101 | void Vignette::draw() 102 | { 103 | if ( mScale < 2.24f ) { 104 | 105 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, constrain(2.0f - mScale, 0.0f, 1.0f) ) ); 106 | 107 | mTex.enableAndBind(); 108 | glEnableClientState( GL_VERTEX_ARRAY ); 109 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 110 | 111 | glVertexPointer( 2, GL_FLOAT, sizeof(VertexData), mVerts ); 112 | glTexCoordPointer( 2, GL_FLOAT, sizeof(VertexData), &mVerts[0].texture ); 113 | 114 | glDrawArrays( GL_TRIANGLES, 0, mTotalVertices ); 115 | 116 | glDisableClientState( GL_VERTEX_ARRAY ); 117 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 118 | mTex.disable(); 119 | } 120 | } 121 | 122 | void Vignette::setShowing( bool b ) 123 | { 124 | mShowing = b; 125 | mCallbacksToggled.call( b ); 126 | } 127 | 128 | -------------------------------------------------------------------------------- /src/World.h: -------------------------------------------------------------------------------- 1 | /* 2 | * World.h 3 | * Kepler 4 | * 5 | * Created by Robert Hodgin on 2/25/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "CinderIPod.h" 13 | #include "cinder/app/AppCocoaTouch.h" 14 | #include "cinder/Vector.h" 15 | #include "cinder/Font.h" 16 | #include "cinder/gl/gl.h" 17 | #include "cinder/gl/Texture.h" 18 | #include "cinder/Surface.h" 19 | 20 | #include "Node.h" 21 | #include "NodeArtist.h" 22 | #include "NodeAlbum.h" 23 | #include "NodeTrack.h" 24 | 25 | #include "Filter.h" 26 | 27 | #include "Stars.h" 28 | #include "StarGlows.h" 29 | #include "OrbitRing.h" 30 | #include "PlanetRing.h" 31 | #include "Constellation.h" 32 | 33 | class World { 34 | 35 | public: 36 | 37 | World() { mSpheresInitialized = false; mIsInitialized = false; }; 38 | ~World() {}; 39 | 40 | void setup(); 41 | 42 | void initNodes( const vector &artists, 43 | const ci::Font &font, 44 | const ci::Font &smallFont, 45 | const ci::Surface &hiResSurfaces, 46 | const ci::Surface &loResSurfaces, 47 | const ci::Surface &noAlbumArt ); 48 | 49 | void setFilter(FilterRef filterRef); 50 | int getNumFilteredNodes() const { return mFilteredNodes.size(); } 51 | 52 | void updateIsPlaying( uint64_t artistId, uint64_t albumId, uint64_t trackId ); 53 | void selectHierarchy( uint64_t artistId, uint64_t albumId, uint64_t trackId ); 54 | NodeTrack* getTrackNodeById( uint64_t artistId, uint64_t albumId, uint64_t trackId ); 55 | NodeAlbum* getAlbumNodeById( uint64_t artistId, uint64_t albumId ); 56 | NodeArtist* getArtistNodeById(const uint64_t theId) { return mNodesById[theId]; } 57 | NodeTrack* selectPlayingHierarchy( uint64_t artistId, uint64_t albumId, uint64_t trackId ); 58 | 59 | void updateAgainstCurrentFilter(); 60 | 61 | void checkForNameTouch( std::vector &nodes, const ci::Vec2f &pos ); 62 | 63 | void update( float param1, float param2 ); 64 | void updateGraphics( const ci::CameraPersp &cam, const ci::Vec2f ¢er, const ci::Vec3f &bbRight, const ci::Vec3f &bbUp, const float &zoomAlpha ); 65 | 66 | void drawStarsVertexArray(); 67 | void drawStarGlowsVertexArray(); 68 | void drawNames( const ci::CameraPersp &cam, float pinchAlphaOffset, float angle ); 69 | void drawOrbitRings( float pinchAlphaOffset, float camAlpha, float fadeInAlphaToArtist, float fadeInArtistToAlbum ); 70 | void drawConstellation(); 71 | void drawTouchHighlights( float zoomAlpha ); 72 | void drawRings( const ci::gl::Texture &tex, float camZPos ); 73 | void drawHitAreas(); 74 | 75 | std::vector getUnsortedNodes( int fromGen, int toGen ); 76 | std::vector sortNodes( std::vector unsortedNodes ); 77 | 78 | NodeTrack *mPlayingTrackNode; 79 | 80 | private: 81 | 82 | std::vector mNodes; 83 | std::map mNodesById; 84 | std::vector mFilteredNodes; 85 | FilterRef mFilterRef; 86 | 87 | /////////////// 88 | 89 | int mAge; 90 | int mEndRepulseAge; 91 | bool mIsRepulsing; 92 | bool mIsInitialized; 93 | bool mSpheresInitialized; 94 | 95 | /////////////// 96 | 97 | void repulseNodes(); 98 | 99 | /////////////// 100 | 101 | // VERTEX ARRAYS 102 | Stars mStars; 103 | StarGlows mStarGlows; 104 | OrbitRing mOrbitRing; 105 | PlanetRing mPlanetRing; 106 | Constellation mConstellation; 107 | 108 | // SPHERE LOD VERTEX ARRAYS 109 | BloomSphere mTySphere, mLoSphere, mMdSphere, mHiSphere; 110 | 111 | }; 112 | 113 | bool nodeSortFunc(Node* a, Node* b); 114 | -------------------------------------------------------------------------------- /src/Stars.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Stars.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/13/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "Stars.h" 10 | #include "cinder/gl/gl.h" 11 | #include "Globals.h" // mumble 12 | #include "NodeArtist.h" 13 | 14 | using namespace ci; 15 | using namespace std; 16 | 17 | Stars::Stars() 18 | { 19 | mVerts = NULL; 20 | mPrevTotalVertices = -1; 21 | } 22 | 23 | Stars::~Stars() 24 | { 25 | if (mVerts != NULL) { 26 | delete[] mVerts; 27 | mVerts = NULL; 28 | } 29 | } 30 | 31 | void Stars::setup( const vector &nodes, const ci::Vec3f &bbRight, const ci::Vec3f &bbUp, const float &zoomAlpha ) 32 | { 33 | mTotalVertices = nodes.size() * 6; 34 | 35 | if (mTotalVertices != mPrevTotalVertices) { 36 | if (mVerts != NULL) { 37 | delete[] mVerts; 38 | mVerts = NULL; 39 | } 40 | if (mTotalVertices > 0) { 41 | mVerts = new VertexData[mTotalVertices]; 42 | mPrevTotalVertices = mTotalVertices; 43 | } 44 | } 45 | 46 | int vIndex = 0; 47 | const float scaleOffset = 0.5f - constrain( G_ARTIST_LEVEL - G_ZOOM, 0.0f, 1.0f ) * 0.25f; // 0.25 -> 0.5 48 | const float zoomOffset = zoomAlpha * 1.5f; 49 | 50 | for( vector::const_iterator it = nodes.begin(); it != nodes.end(); ++it ){ 51 | 52 | Vec3f pos = (*it)->mPos; 53 | Color c = (*it)->mColor; 54 | Vec4f col = Vec4f(c.r, c.g, c.b, 1.0); 55 | 56 | float radius = (*it)->mRadius * scaleOffset * 0.85f + ( 0.5f - scaleOffset ); 57 | 58 | if( !(*it)->mIsHighlighted ){ 59 | radius -= zoomOffset; 60 | } 61 | 62 | Vec3f right = bbRight * radius; 63 | Vec3f up = bbUp * radius; 64 | 65 | Vec3f p1 = pos - right - up; 66 | Vec3f p2 = pos + right - up; 67 | Vec3f p3 = pos - right + up; 68 | Vec3f p4 = pos + right + up; 69 | 70 | mVerts[vIndex].vertex = p1; 71 | mVerts[vIndex].texture = Vec2f(0.0f,0.0f); 72 | mVerts[vIndex].color = col; 73 | vIndex++; 74 | 75 | mVerts[vIndex].vertex = p2; 76 | mVerts[vIndex].texture = Vec2f(1.0f,0.0f); 77 | mVerts[vIndex].color = col; 78 | vIndex++; 79 | 80 | mVerts[vIndex].vertex = p3; 81 | mVerts[vIndex].texture = Vec2f(0.0f,1.0f); 82 | mVerts[vIndex].color = col; 83 | vIndex++; 84 | 85 | mVerts[vIndex].vertex = p2; 86 | mVerts[vIndex].texture = Vec2f(1.0f,0.0f); 87 | mVerts[vIndex].color = col; 88 | vIndex++; 89 | 90 | mVerts[vIndex].vertex = p3; 91 | mVerts[vIndex].texture = Vec2f(0.0f,1.0f); 92 | mVerts[vIndex].color = col; 93 | vIndex++; 94 | 95 | mVerts[vIndex].vertex = p4; 96 | mVerts[vIndex].texture = Vec2f(1.0f,1.0f); 97 | mVerts[vIndex].color = col; 98 | vIndex++; 99 | } 100 | } 101 | 102 | void Stars::draw( ) 103 | { 104 | glEnableClientState( GL_VERTEX_ARRAY ); 105 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 106 | glEnableClientState( GL_COLOR_ARRAY ); 107 | 108 | // TODO: maybe use a DYNAMIC VBO, or a VAO (as Apple recommends) 109 | // we don't use POINT_SPRITE because we need to draw BIG stars 110 | 111 | glVertexPointer( 3, GL_FLOAT, sizeof(VertexData), mVerts ); 112 | glTexCoordPointer( 2, GL_FLOAT, sizeof(VertexData), &mVerts[0].texture ); 113 | glColorPointer( 4, GL_FLOAT, sizeof(VertexData), &mVerts[0].color ); 114 | 115 | glDrawArrays( GL_TRIANGLES, 0, mTotalVertices ); 116 | 117 | glDisableClientState( GL_VERTEX_ARRAY ); 118 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 119 | glDisableClientState( GL_COLOR_ARRAY ); 120 | } 121 | -------------------------------------------------------------------------------- /src/StarGlows.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // StarGlows.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/13/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "StarGlows.h" 10 | #include "NodeArtist.h" 11 | 12 | using namespace ci; 13 | using namespace std; 14 | 15 | StarGlows::StarGlows() 16 | { 17 | mVerts = NULL; 18 | mPrevTotalVertices = -1; 19 | } 20 | 21 | StarGlows::~StarGlows() 22 | { 23 | if (mVerts != NULL) { 24 | delete[] mVerts; 25 | mVerts = NULL; 26 | } 27 | } 28 | 29 | void StarGlows::setup( const vector &filteredNodes, const Vec3f &bbRight, const Vec3f &bbUp, const float &zoomAlpha ) 30 | { 31 | mTotalVertices = filteredNodes.size() * 6; // 6 = 2 triangles per quad 32 | 33 | if (mTotalVertices != mPrevTotalVertices) { 34 | if (mVerts != NULL) { 35 | delete[] mVerts; 36 | } 37 | mVerts = new VertexData[mTotalVertices]; 38 | mPrevTotalVertices = mTotalVertices; 39 | } 40 | 41 | int vIndex = 0; 42 | 43 | for( vector::const_iterator it = filteredNodes.begin(); it != filteredNodes.end(); ++it ) 44 | { 45 | Vec3f pos = (*it)->mPos; 46 | float r = (*it)->mRadius * ( (*it)->mEclipseStrength * 2.0f + 1.5f ); // HERE IS WHERE YOU CAN MAKE THE GLOW HUGER/BIGGER/AWESOMER 47 | if( (*it)->mIsSelected ) 48 | r *= 0.1f; 49 | 50 | float alpha = (*it)->mDistFromCamZAxisPer * ( 1.0f - (*it)->mEclipseStrength ); 51 | //if( !(*it)->mIsSelected && !(*it)->mIsPlaying ) 52 | // alpha = 1.0f - zoomAlpha; 53 | 54 | Color c = (*it)->mGlowColor; 55 | Vec4f col = Vec4f( c.r, c.g, c.b, alpha ); 56 | 57 | Vec3f right = bbRight * r; 58 | Vec3f up = bbUp * r; 59 | 60 | Vec3f p1 = pos - right - up; 61 | Vec3f p2 = pos + right - up; 62 | Vec3f p3 = pos - right + up; 63 | Vec3f p4 = pos + right + up; 64 | 65 | mVerts[vIndex].vertex = p1; 66 | mVerts[vIndex].texture = Vec2f(0.0f,0.0f); 67 | mVerts[vIndex].color = col; 68 | vIndex++; 69 | 70 | mVerts[vIndex].vertex = p2; 71 | mVerts[vIndex].texture = Vec2f(1.0f,0.0f); 72 | mVerts[vIndex].color = col; 73 | vIndex++; 74 | 75 | mVerts[vIndex].vertex = p3; 76 | mVerts[vIndex].texture = Vec2f(0.0f,1.0f); 77 | mVerts[vIndex].color = col; 78 | vIndex++; 79 | 80 | mVerts[vIndex].vertex = p2; 81 | mVerts[vIndex].texture = Vec2f(1.0f,0.0f); 82 | mVerts[vIndex].color = col; 83 | vIndex++; 84 | 85 | mVerts[vIndex].vertex = p3; 86 | mVerts[vIndex].texture = Vec2f(0.0f,1.0f); 87 | mVerts[vIndex].color = col; 88 | vIndex++; 89 | 90 | mVerts[vIndex].vertex = p4; 91 | mVerts[vIndex].texture = Vec2f(1.0f,1.0f); 92 | mVerts[vIndex].color = col; 93 | vIndex++; 94 | } 95 | } 96 | 97 | void StarGlows::draw() 98 | { 99 | glEnableClientState( GL_VERTEX_ARRAY ); 100 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 101 | glEnableClientState( GL_COLOR_ARRAY ); 102 | 103 | // TODO: could we use a DYNAMIC VBO or a "VAO" (as Apple recommends) to manage this? 104 | // NB:- we don't use POINT_SPRITE because we need to draw BIG points sometimes 105 | 106 | glVertexPointer( 3, GL_FLOAT, sizeof(VertexData), mVerts ); 107 | glTexCoordPointer( 2, GL_FLOAT, sizeof(VertexData), &mVerts[0].texture ); 108 | glColorPointer( 4, GL_FLOAT, sizeof(VertexData), &mVerts[0].color ); 109 | 110 | glDrawArrays( GL_TRIANGLES, 0, mTotalVertices ); 111 | 112 | glDisableClientState( GL_VERTEX_ARRAY ); 113 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 114 | glDisableClientState( GL_COLOR_ARRAY ); 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/TextureLoader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // TextureLoader.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 7/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "TextureLoader.h" 10 | #include "cinder/app/AppCocoaTouch.h" // for loadResource 11 | #include "cinder/ImageIo.h" 12 | #include "TaskQueue.h" 13 | 14 | using namespace ci; 15 | using namespace ci::app; 16 | 17 | void TextureLoader::addRequest( int texId, std::string fileName ) 18 | { 19 | addRequest( texId, fileName, ci::gl::Texture::Format() ); 20 | } 21 | 22 | void TextureLoader::addRequest( int texId, std::string fileName, ci::gl::Texture::Format format ) 23 | { 24 | mRequestsMutex.lock(); 25 | mRequests.push_back( Request(texId, fileName, format) ); 26 | mRequestsMutex.unlock(); 27 | mTotalRequests++; 28 | } 29 | 30 | //void TextureLoader::addRequest( int texId, std::string compressedFileName, ci::Vec2i size ) 31 | //{ 32 | // // FIXME 33 | //// mTotalRequests++; 34 | //} 35 | 36 | //gl::Texture KeplerApp::loadCompressedTexture(const std::string &dataPath, const Vec2i &imageSize) 37 | //{ 38 | // // NB:- compressed textures *must* be square 39 | // // also, file sizes are actually larger than jpg 40 | // // ... but it stays compressed on the GPU for more awesome 41 | // gl::Texture::Format compressedFormat; 42 | // compressedFormat.setInternalFormat(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); 43 | // compressedFormat.enableMipmapping(false); // TODO: talk to Ryan about mipmapped compressed textures 44 | // compressedFormat.setMagFilter( GL_LINEAR ); 45 | // compressedFormat.setMinFilter( GL_LINEAR ); 46 | // 47 | // DataSourceRef dataSource = loadResource(dataPath); 48 | // const size_t dataSize = dataSource->getBuffer().getDataSize(); 49 | // const uint8_t *data = static_cast(dataSource->getBuffer().getData()); 50 | // return gl::Texture::withCompressedData(data, imageSize.x, imageSize.y, dataSize, compressedFormat); 51 | //} 52 | 53 | void TextureLoader::start() 54 | { 55 | TaskQueue::pushTask( std::bind( std::mem_fun( &TextureLoader::loadSurfaces ), this ) ); 56 | } 57 | 58 | void TextureLoader::loadSurfaces() 59 | { 60 | for (int i = 0; i < mRequests.size(); i++) { 61 | mRequestsMutex.lock(); 62 | std::string path = mRequests[i].mFileName; 63 | mRequestsMutex.unlock(); 64 | // no lock for the long running part... 65 | Surface surface = loadImage( loadResource( path ) ); 66 | mRequestsMutex.lock(); 67 | mRequests[i].mSurface = surface; 68 | mRequestsMutex.unlock(); 69 | mRequestsComplete++; 70 | // called on the UI thread... 71 | UiTaskQueue::pushTask( std::bind( std::mem_fun( &TextureLoader::surfaceLoaded ), this ) ); 72 | } 73 | } 74 | 75 | void TextureLoader::surfaceLoaded() 76 | { 77 | // std::cout << "TextureLoader::surfaceLoaded()" << std::endl; 78 | 79 | if (mTextures.size() == mTotalRequests) { 80 | return; 81 | } 82 | 83 | // one texture per frame 84 | if (mTextures.size() < mRequestsComplete) { 85 | // std::cout << "TextureLoader::surfaceLoaded checking lock... "; 86 | 87 | // if mRequestsMutex isn't already locked (don't block, we're on the UI thread) 88 | if (mRequestsMutex.try_lock()) { 89 | // std::cout << " got lock!" << std::endl; 90 | int index = mTextures.size(); 91 | mTextures[ mRequests[index].mTexId ] = gl::Texture( mRequests[index].mSurface, mRequests[index].mFormat ); 92 | mRequests[index].mSurface.reset(); 93 | mRequestsMutex.unlock(); 94 | } 95 | else { 96 | // std::cout << " try again next time!" << std::endl; 97 | // try again 98 | UiTaskQueue::pushTask( std::bind( std::mem_fun( &TextureLoader::surfaceLoaded ), this ) ); 99 | } 100 | } 101 | 102 | if (mTextures.size() == mTotalRequests) { 103 | // std::cout << "TextureLoader::surfaceLoaded complete!" << std::endl; 104 | mRequests.clear(); 105 | mCbComplete.call( this ); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/SettingsPanel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsPanel.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 8/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | #include "cinder/app/AppCocoaTouch.h" 14 | #include "cinder/gl/Texture.h" 15 | #include "cinder/Font.h" 16 | #include "cinder/Text.h" 17 | #include "cinder/Utilities.h" 18 | 19 | #include "BloomNode.h" 20 | #include "Buttons.h" 21 | #include "Slider.h" 22 | #include "TextLabel.h" 23 | #include "CinderIPodPlayer.h" 24 | 25 | class SettingsPanel; 26 | typedef std::shared_ptr SettingsPanelRef; 27 | 28 | class SettingsPanel : public BloomNode { 29 | public: 30 | 31 | enum ButtonId { NO_BUTTON = 2000, 32 | SHUFFLE, REPEAT, 33 | HELP, AUTO_MOVE, DRAW_RINGS, DRAW_TEXT, USE_GYRO, DEBUG_FEATURE, 34 | PARAMSLIDER1, PARAMSLIDER2, 35 | LAST_BUTTON }; 36 | 37 | SettingsPanel(): mOpacity(1.0f) {}; 38 | ~SettingsPanel() {}; 39 | 40 | void setup( const ci::Vec2f &interfaceSize, 41 | ci::ipod::Player *player, 42 | const ci::Font &font, 43 | const ci::gl::Texture &smallButtonsTex ); 44 | 45 | void update(); 46 | 47 | // State stuff, passed onto UI classes directly... 48 | void setHelpOn(bool on) { mHelpButton->setOn(on); }; 49 | void setDebugOn(bool on) { mDebugButton->setOn(on); }; 50 | void setGyroOn(bool on) { mGyroButton->setOn(on); }; 51 | void setOrbitsOn(bool on) { mOrbitsButton->setOn(on); }; 52 | void setLabelsOn(bool on) { mLabelsButton->setOn(on); }; 53 | void setShuffleOn(bool on) { mShuffleButton->setOn(on); }; 54 | void setScreensaverOn(bool on){ mScreensaverButton->setOn(on); }; 55 | void setRepeatMode(ci::ipod::Player::RepeatMode state) 56 | { 57 | int stateInt = state == ci::ipod::Player::RepeatModeNone ? 0 : 58 | state == ci::ipod::Player::RepeatModeAll ? 1 : 59 | state == ci::ipod::Player::RepeatModeOne ? 2 : 0; // 0 for RepeatModeDefault 60 | mRepeatButton->setState(stateInt); 61 | }; 62 | float getParamSlider1Value(){ return mParamSlider1->getValue(); } 63 | float getParamSlider2Value(){ return mParamSlider2->getValue(); } 64 | 65 | bool addedToScene(); // from BloomNode 66 | void deepDraw(); 67 | 68 | // used in UiLayer layout... 69 | float getHeight(); 70 | 71 | void setOpacity( float opacity ) { mOpacity = opacity; } 72 | 73 | private: 74 | 75 | // instantiate and set fonts/areas/textures (called once) 76 | void createChildren( const ci::Font &font, const ci::gl::Texture &uiSmallButtonsTex ); 77 | 78 | // add everything (called once) 79 | void addChildren(); 80 | 81 | // set positions (can be called repeatedly whenever interfaceSize changes) 82 | void setInterfaceSize( const ci::Vec2f &interfaceSize ); 83 | 84 | // for detecting orientation change, updating layout 85 | ci::Vec2f mInterfaceSize; 86 | 87 | float mOpacity; 88 | 89 | ///////////// UI Classes: 90 | 91 | // Remember: 92 | // 93 | // -- SimpleButton is just a trigger (down when touched, up when not) 94 | // -- ToggleButton is for things that are sticky, on or off 95 | // -- TwoStateButton is really just for Play/Pause, but who knows 96 | // -- ThreeStateButton is really just for RepeatMode, but who knows 97 | // 98 | // And furthermore thusly: 99 | // 100 | // -- TextLabel is for simple static labels 101 | // -- ScrollingLabel will flutter back and forth if you tell it the lastSomethingOrOtherTime 102 | // -- TimeLabel will format a number of seconds as mm:ss 103 | // 104 | 105 | ToggleButton *mHelpButton; 106 | ToggleButton *mScreensaverButton; 107 | ToggleButton *mOrbitsButton; 108 | ToggleButton *mLabelsButton; 109 | ToggleButton *mDebugButton; 110 | ToggleButton *mGyroButton; 111 | ToggleButton *mShuffleButton; 112 | ThreeStateButton *mRepeatButton; 113 | 114 | TextLabel *mParamSlider1Label; 115 | Slider *mParamSlider1; 116 | TextLabel *mParamSlider2Label; 117 | Slider *mParamSlider2; 118 | }; -------------------------------------------------------------------------------- /blocks/BloomTasks/src/TaskQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // TaskQueue.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 8/17/11. 6 | // Copyright 2011 Bloom Studio, Inc. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include "cinder/app/AppBasic.h" 14 | #include "cinder/Cinder.h" 15 | #include "cinder/Thread.h" 16 | #include "cinder/Function.h" 17 | 18 | typedef std::function VoidFunc; 19 | 20 | class TaskQueue { 21 | 22 | public: 23 | 24 | static void pushTask( VoidFunc f ) 25 | { 26 | // TODO: later, optionally use a single thread and queue the tasks 27 | // e.g. http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html 28 | // for now, a thread per task will help spec out the right interface: 29 | std::thread taskThread( &TaskQueue::doWork, f ); 30 | } 31 | 32 | private: 33 | 34 | static void doWork( VoidFunc f ) 35 | { 36 | // Cinder's ThreadSetup class ensures that the OS know's what's up 37 | // (creates and drains an autorelease pool, etc) 38 | ci::ThreadSetup threadSetup; 39 | 40 | // otherwise we'd need: 41 | // NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; 42 | 43 | // do the work: 44 | f(); 45 | 46 | // cleanup (now handled by ThreadSetup): 47 | // http://stackoverflow.com/questions/797419/whats-the-difference-between-sending-release-or-drain-to-an-autorelease-pool 48 | // [autoreleasepool release]; 49 | } 50 | 51 | }; 52 | 53 | class UiTaskQueue { 54 | 55 | public: 56 | 57 | static int pushTask( VoidFunc f ) 58 | { 59 | mFunctionsMutex.lock(); 60 | mFunctions.push( f ); 61 | mFunctionsMutex.unlock(); 62 | return mTotalTasks++; 63 | } 64 | 65 | static bool isTaskComplete( uint64_t taskId ) 66 | { 67 | return mCompletedTasks > taskId; 68 | } 69 | 70 | // only call from main thread, no canceling from background threads yet :( 71 | static void cancelTask( uint64_t taskId ) 72 | { 73 | if (!isTaskComplete(taskId)) { 74 | mCanceledIds.insert(taskId); 75 | } 76 | } 77 | 78 | // call this from the UI thread, or pain will occur 79 | // default ~5ms budget (but will always do at least one call) 80 | static void update( const float &budgetSeconds = 0.005f ) 81 | { 82 | // empty while loop *shiver* 83 | const float t = ci::app::getElapsedSeconds(); 84 | while ( popTask() && ci::app::getElapsedSeconds() - t < budgetSeconds ); 85 | } 86 | 87 | private: 88 | 89 | // returns true if it got a lock and has more tasks, false otherwise 90 | static bool popTask( ) 91 | { 92 | if (mFunctionsMutex.try_lock()) { 93 | if (mFunctions.empty()) { 94 | mFunctionsMutex.unlock(); 95 | return false; 96 | } 97 | else { 98 | // remember this id and increment too; 99 | // (it's about to be gone from mFunctions so cancelTask won't work anyway) 100 | uint64_t thisTaskId = mCompletedTasks++; 101 | 102 | // grab the next task and remove it; there is no undo 103 | VoidFunc f = mFunctions.front(); 104 | mFunctions.pop(); 105 | 106 | // let callers know if it's worth calling again 107 | bool hasMoreTasks = !mFunctions.empty(); 108 | 109 | // unlock first so that tasks can queue other tasks 110 | mFunctionsMutex.unlock(); 111 | 112 | // if it's not canceled, do it (otherwise just clean up the canceled marker) 113 | std::set::iterator iter = mCanceledIds.find( thisTaskId ); 114 | if ( iter == mCanceledIds.end() ) { 115 | f(); 116 | } 117 | else { 118 | mCanceledIds.erase( iter ); 119 | } 120 | 121 | return hasMoreTasks; 122 | } 123 | } 124 | return false; 125 | } 126 | 127 | static std::mutex mFunctionsMutex; 128 | static std::queue mFunctions; 129 | static uint64_t mCompletedTasks; 130 | static uint64_t mTotalTasks; 131 | static std::set mCanceledIds; // FIXME: no mutex for canceling so not thread safe :( 132 | 133 | }; -------------------------------------------------------------------------------- /src/NotificationOverlay.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationOverlay.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/2/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include "NotificationOverlay.h" 10 | #include 11 | #include 12 | #include 13 | #include "cinder/Font.h" 14 | #include "cinder/Text.h" 15 | #include "Globals.h" 16 | #include "BloomScene.h" 17 | #include "cinder/app/AppCocoaTouch.h" // FIXME: just for time 18 | 19 | using namespace std; 20 | using namespace ci; 21 | using namespace ci::app; 22 | 23 | NotificationOverlay::NotificationOverlay() 24 | { 25 | mActive = false; 26 | mSetup = false; 27 | mFadeDelay = 1.0f; 28 | mFadeDuration = 0.5f; 29 | } 30 | 31 | NotificationOverlay::~NotificationOverlay() 32 | { 33 | hide(); 34 | } 35 | 36 | void NotificationOverlay::setup( const Font &font ) 37 | { 38 | mFont = font; 39 | mSetup = true; 40 | } 41 | 42 | void NotificationOverlay::update() 43 | { 44 | if (!mActive) return; 45 | 46 | // if enough time has passed, hide the overlay (cleanup happens in hide()) 47 | float elapsedSince = app::getElapsedSeconds() - mLastShowTime; 48 | if (elapsedSince > mFadeDelay + mFadeDuration) { 49 | hide(); 50 | } 51 | 52 | mAlpha = 1.0f; 53 | if (elapsedSince > mFadeDelay) { 54 | mAlpha = 1.0f - (elapsedSince - mFadeDelay) / mFadeDuration; 55 | } 56 | 57 | Vec2f interfaceSize = getRoot()->getInterfaceSize(); 58 | 59 | Matrix44f mat; 60 | mat.translate(Vec3f( interfaceSize.x * 0.5f, interfaceSize.y * 0.5f + 184.0f - mMessageTexture.getHeight(), 0.0f )); 61 | setTransform(mat); 62 | } 63 | 64 | void NotificationOverlay::draw() 65 | { 66 | if (!mActive) return; 67 | 68 | gl::enableAdditiveBlending(); // as long as this is the last thing. 69 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, mAlpha ) ); 70 | gl::draw( mMessageTexture, mMessageRect ); 71 | 72 | bool hasOverGraphic = mCurrentSecondSrcArea.getWidth() != 0; 73 | if (hasOverGraphic) { 74 | // under graphic should be dimmer 75 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, mAlpha * 0.25f ) ); 76 | } 77 | // TODO: batch these calls if using the same texture, avoid cinder::gl::draw() overhead? 78 | gl::draw( mCurrentTexture, mCurrentSrcArea, mIconRect ); 79 | 80 | if (hasOverGraphic) { 81 | // overgraphic should be same alpha as text? 82 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, mAlpha ) ); 83 | gl::draw( mCurrentTexture, mCurrentSecondSrcArea, mIconRect ); 84 | } 85 | } 86 | 87 | void NotificationOverlay::show(const gl::Texture &texture, const Area &srcArea, const string &message) 88 | { 89 | show(texture, srcArea, Area(0,0,0,0), message); 90 | } 91 | 92 | void NotificationOverlay::show( const ci::gl::Texture &texture, const ci::Area &srcArea1, const ci::Area &srcArea2, const std::string &message ) 93 | { 94 | if (!mSetup) return; 95 | 96 | mCurrentTexture = texture; 97 | mCurrentSrcArea = srcArea1; 98 | mCurrentSecondSrcArea = srcArea2; 99 | mCurrentMessage = message; 100 | 101 | TextLayout layout; 102 | layout.setFont( mFont ); 103 | layout.setColor( ColorA( BRIGHT_BLUE, 0.5f ) ); 104 | vector results; 105 | boost::split(results, message, boost::is_any_of("\n")); 106 | for (int i = 0; i < results.size(); i++) { 107 | layout.addCenteredLine( results[i] ); 108 | } 109 | mMessageTexture = gl::Texture( layout.render( true, true ) ); 110 | 111 | Vec2f iconSize = mCurrentSrcArea.getSize(); 112 | mIconRect = Rectf( -iconSize/2.0f, iconSize/2.0f ); 113 | 114 | float halfWidth = mMessageTexture.getWidth() * 0.5f; 115 | Vec2f messageTopLeft( -halfWidth, mIconRect.y2 - 10.0f ); 116 | Vec2f messageBottomRight( halfWidth, mIconRect.y2 + mMessageTexture.getHeight() - 10.0f ); 117 | mMessageRect = Rectf( messageTopLeft, messageBottomRight ); 118 | 119 | mActive = true; 120 | mLastShowTime = app::getElapsedSeconds(); 121 | } 122 | 123 | void NotificationOverlay::showLetter( const char &c, const string &message, const Font &hugeFont ) 124 | { 125 | if (!mSetup) return; 126 | 127 | TextLayout charLayout; 128 | charLayout.setFont( hugeFont ); 129 | charLayout.setColor( ColorA( BRIGHT_BLUE, 0.5f ) ); 130 | string s = ""; 131 | s += c; 132 | charLayout.addCenteredLine( s ); 133 | 134 | gl::Texture texture = gl::Texture( charLayout.render( true, true ) ); 135 | 136 | show( texture, 137 | Area( 0, 0, texture.getWidth(), texture.getHeight() + 15.0f ), 138 | Area( 0, 0, 0, 0 ), 139 | message ); 140 | } 141 | 142 | void NotificationOverlay::hide() 143 | { 144 | mActive = false; 145 | mCurrentTexture.reset(); 146 | } 147 | -------------------------------------------------------------------------------- /src/PlayControls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PlayControls.h 3 | * Kepler 4 | * 5 | * Created by Tom Carden on 3/7/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | 14 | #include "cinder/app/AppCocoaTouch.h" 15 | #include "cinder/gl/Texture.h" 16 | #include "cinder/Font.h" 17 | #include "cinder/Text.h" 18 | #include "cinder/Utilities.h" 19 | 20 | #include "BloomNode.h" 21 | #include "Buttons.h" 22 | #include "Slider.h" 23 | #include "TextLabel.h" 24 | #include "TimeLabel.h" 25 | #include "TextureRect.h" 26 | #include "ScrollingLabel.h" 27 | #include "CinderIPodPlayer.h" 28 | 29 | class PlayControls; 30 | typedef std::shared_ptr PlayControlsRef; 31 | 32 | class PlayControls : public BloomNode { 33 | public: 34 | 35 | enum ButtonId { NO_BUTTON = 1000, 36 | SHOW_PLAYLIST_FILTER, SHOW_ALPHA_FILTER, 37 | GOTO_GALAXY, GOTO_CURRENT_TRACK, SETTINGS, 38 | PREV_TRACK, PLAY_PAUSE, NEXT_TRACK, 39 | SLIDER, 40 | LAST_BUTTON }; 41 | 42 | PlayControls(): mOpacity(1.0f) {}; 43 | ~PlayControls() {}; 44 | 45 | void setup( Vec2f interfaceSize, 46 | ci::ipod::Player *player, 47 | const ci::Font &font, 48 | const ci::Font &fontSmall, 49 | const ci::gl::Texture &buttonsTex ); 50 | 51 | void update(); 52 | 53 | // used in UiLayer layout... 54 | float getHeight(); 55 | 56 | void setOpacity( float opacity ) { mOpacity = opacity; } 57 | 58 | void setPlaylistButtonVisible( bool visible ); 59 | 60 | // State stuff, passed onto UI classes directly... 61 | // (not gettable, state lives elsewhere and UI changes are handled with callbacks) 62 | // (all these things should be called in App::update()) 63 | // TODO: investigate doing this automagically with &references or *pointers? 64 | 65 | void setShowSettingsOn(bool on) { mShowSettingsButton->setOn(on); } 66 | void setPlayingOn(bool on) { mPlayPauseButton->setOn(on); } 67 | void setAlphaOn(bool on) { mAlphaButton->setOn(on); }; 68 | void setPlaylistOn(bool on) { mPlaylistButton->setOn(on); }; 69 | 70 | void setElapsedSeconds(int elapsedTime) { mElapsedTimeLabel->setSeconds(elapsedTime); } 71 | void setRemainingSeconds(int remainingTime) { mRemainingTimeLabel->setSeconds(remainingTime); } 72 | void setCurrentTrack(std::string currentTrack) { mTrackInfoLabel->setText(currentTrack); } 73 | void enablePlayerControls( bool enable = true ); 74 | void disablePlayerControls() { enablePlayerControls(false); } 75 | 76 | void setPlayheadValue(float value) { mPlayheadSlider->setValue(value); } 77 | float getPlayheadValue() { return mPlayheadSlider->getValue(); } 78 | bool isPlayheadDragging() { return mPlayheadSlider->isDragging(); } 79 | void cancelPlayheadDrag() { mPlayheadSlider->setIsDragging(false); } 80 | 81 | bool addedToScene(); // from BloomNode 82 | 83 | // override so we can batch geometry 84 | virtual void deepDraw(); 85 | 86 | private: 87 | 88 | // instantiate and set fonts/areas/textures (called once) 89 | void createChildren( const Font &font, const Font &fontSmall, const gl::Texture &uiButtonsTex ); 90 | 91 | // add everything (called once) 92 | void addChildren(); 93 | 94 | // set positions (can be called repeatedly whenever interfaceSize changes) 95 | void setInterfaceSize( ci::Vec2f interfaceSize ); 96 | 97 | ci::Vec2f mInterfaceSize; // for detecting orientation change, updating layout 98 | 99 | float mOpacity; 100 | 101 | ///////////// UI Classes: 102 | 103 | // Remember: 104 | // 105 | // -- SimpleButton is just a trigger (down when touched, up when not) 106 | // -- ToggleButton is for things that are sticky, on or off 107 | // -- TwoStateButton is really just for Play/Pause, but who knows 108 | // 109 | // And furthermore thusly: 110 | // 111 | // -- TextLabel is for simple static labels 112 | // -- ScrollingLabel will flutter back and forth if you tell it the lastSomethingOrOtherTime 113 | // -- TimeLabel will format a number of seconds as mm:ss 114 | // 115 | 116 | // buttons for flying... 117 | SimpleButton *mGalaxyButton; 118 | SimpleButton *mCurrentTrackButton; 119 | 120 | // current track info and playhead... 121 | ScrollingLabel *mTrackInfoLabel; 122 | TextureRect *mCoverLeftTextureRect; 123 | TextureRect *mCoverRightTextureRect; 124 | TimeLabel *mElapsedTimeLabel; 125 | Slider *mPlayheadSlider; 126 | TimeLabel *mRemainingTimeLabel; 127 | 128 | // filters 129 | ToggleButton *mAlphaButton; 130 | ToggleButton *mPlaylistButton; 131 | 132 | // settings 133 | ToggleButton *mShowSettingsButton; 134 | 135 | // track skip and play/pause controls 136 | SimpleButton *mPreviousTrackButton; 137 | TwoStateButton *mPlayPauseButton; 138 | SimpleButton *mNextTrackButton; 139 | }; -------------------------------------------------------------------------------- /src/BloomSphere.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // BloomSphere.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 6/12/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "cinder/CinderMath.h" 11 | #include "cinder/Vector.h" 12 | #include "BloomSphere.h" 13 | 14 | using namespace ci; 15 | using namespace std; 16 | 17 | namespace bloom { 18 | 19 | void BloomSphere::setup( int segments ) 20 | { 21 | if (mInited) { 22 | glDeleteBuffers(1, &mVBO); 23 | } 24 | 25 | mNumVerts = segments * (segments/2) * 2 * 3; 26 | VertexData *verts = new VertexData[ mNumVerts ]; 27 | 28 | const float TWO_PI = 2.0f * M_PI; 29 | 30 | int vert = 0; 31 | for( int j = 0; j < segments / 2; j++ ) { 32 | 33 | float theta1 = (float)j * TWO_PI / (float)segments - ( M_PI_2 ); 34 | float cosTheta1 = cos( theta1 ); 35 | float sinTheta1 = sin( theta1 ); 36 | 37 | float theta2 = (float)(j + 1) * TWO_PI / (float)segments - ( M_PI_2 ); 38 | float cosTheta2 = cos( theta2 ); 39 | float sinTheta2 = sin( theta2 ); 40 | 41 | Vec3f oldv1, oldv2, newv1, newv2; 42 | Vec2f oldt1, oldt2, newt1, newt2; 43 | 44 | for( int i = 0; i <= segments; i++ ) { 45 | oldv1 = newv1; 46 | oldv2 = newv2; 47 | 48 | oldt1 = newt1; 49 | oldt2 = newt2; 50 | 51 | float invSegs = 1.0f / (float)segments; 52 | float theta3 = (float)i * TWO_PI * invSegs; 53 | float cosTheta3 = cos( theta3 ); 54 | float sinTheta3 = sin( theta3 ); 55 | 56 | float invI = (float)i * invSegs; 57 | float u = 0.999f - invI; 58 | float v1 = 0.999f - 2.0f * (float)j * invSegs; 59 | float v2 = 0.999f - 2.0f * (float)(j+1) * invSegs; 60 | 61 | newt1 = Vec2f( u, v1 ); 62 | newt2 = Vec2f( u, v2 ); 63 | 64 | newv1 = Vec3f( cosTheta1 * cosTheta3, sinTheta1, cosTheta1 * sinTheta3 ); 65 | newv2 = Vec3f( cosTheta2 * cosTheta3, sinTheta2, cosTheta2 * sinTheta3 ); 66 | 67 | if( i > 0 ){ 68 | verts[vert].vertex = oldv1; 69 | verts[vert].texture = oldt1; 70 | vert++; 71 | 72 | verts[vert].vertex = oldv2; 73 | verts[vert].texture = oldt2; 74 | vert++; 75 | 76 | verts[vert].vertex = newv1; 77 | verts[vert].texture = newt1; 78 | vert++; 79 | 80 | verts[vert].vertex = oldv2; 81 | verts[vert].texture = oldt2; 82 | vert++; 83 | 84 | verts[vert].vertex = newv2; 85 | verts[vert].texture = newt2; 86 | vert++; 87 | 88 | verts[vert].vertex = newv1; 89 | verts[vert].texture = newt1; 90 | vert++; 91 | } 92 | } 93 | } 94 | 95 | // do VBO (there are more complex ways, let's try this first) 96 | // (other things to try include VAOs, with glGenVertexArraysOES?) 97 | glGenBuffers(1, &mVBO); 98 | glBindBuffer(GL_ARRAY_BUFFER, mVBO); 99 | glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * mNumVerts, verts, GL_STATIC_DRAW); 100 | glBindBuffer(GL_ARRAY_BUFFER, 0); // Leave no VBO bound. 101 | 102 | delete[] verts; 103 | 104 | mInited = true; 105 | } 106 | 107 | void BloomSphere::draw() 108 | { 109 | // here's the old vertex array way... 110 | // glVertexPointer( 3, GL_FLOAT, sizeof(VertexData), &mVerts[0].vertex ); 111 | // glNormalPointer( GL_FLOAT, sizeof(VertexData), &mVerts[0].vertex ); 112 | // glTexCoordPointer( 2, GL_FLOAT, sizeof(VertexData), &mVerts[0].texture ); 113 | 114 | // here's the new vertex buffer way, which needs setting up after mVerts is built in setup 115 | glBindBuffer(GL_ARRAY_BUFFER, mVBO); 116 | glVertexPointer( 3, GL_FLOAT, sizeof(VertexData), 0 ); // last arg becomes an offset instead of an address 117 | glNormalPointer( GL_FLOAT, sizeof(VertexData), 0 ); 118 | glTexCoordPointer( 2, GL_FLOAT, sizeof(VertexData), (GLvoid*)sizeof(Vec3f) ); 119 | glBindBuffer(GL_ARRAY_BUFFER, 0); // Leave no VBO bound. 120 | 121 | glEnableClientState( GL_VERTEX_ARRAY ); 122 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 123 | glEnableClientState( GL_NORMAL_ARRAY ); 124 | glDrawArrays( GL_TRIANGLES, 0, mNumVerts ); 125 | glDisableClientState( GL_VERTEX_ARRAY ); 126 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 127 | glDisableClientState( GL_NORMAL_ARRAY ); 128 | } 129 | 130 | } -------------------------------------------------------------------------------- /src/AlphaChooser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AlphaChooser.cpp 3 | * Kepler 4 | * 5 | * Created by Tom Carden on 3/14/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #include "AlphaChooser.h" 11 | #include "cinder/gl/gl.h" 12 | #include "cinder/Text.h" 13 | #include "Globals.h" 14 | #include "BloomGl.h" 15 | #include "BloomScene.h" 16 | #include "cinder/Utilities.h" // for toString 17 | #include 18 | 19 | using namespace ci; 20 | using namespace ci::app; 21 | using namespace std; 22 | 23 | void AlphaChooser::setup( const Font &font, const Vec2f &interfaceSize ) 24 | { 25 | // Textures 26 | mAlphaString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ#"; 27 | mAlphaIndex = 0; 28 | mAlphaChar = 'A'; 29 | 30 | for( int i=0; igetInterfaceSize(); 123 | if (mInterfaceSize != interfaceSize) { 124 | mInterfaceSize = interfaceSize; 125 | setRects(); 126 | } 127 | } 128 | 129 | void AlphaChooser::draw() 130 | { 131 | // we'll use the bright blue components to draw by frequency 132 | float r = BRIGHT_BLUE.r; 133 | float g = BRIGHT_BLUE.g; 134 | float b = BRIGHT_BLUE.b; 135 | 136 | gl::color( ColorA( r, g, b, mOpacity * 0.125f ) ); 137 | gl::drawLine( mFullRect.getUpperLeft(), mFullRect.getUpperRight() ); 138 | 139 | for( int i=0; i<27; i++ ){ 140 | float c = mNumberAlphaPerChar[i]; 141 | if ( mAlphaString[i] == mAlphaChar ) { 142 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f * mOpacity ) ); 143 | } else if( c > 0.0f ){ 144 | c += 0.3f; 145 | gl::color( ColorA( r*c, g*c, b*c, mOpacity ) ); 146 | } else { 147 | gl::color( ColorA( 0.1f, 0.1f, 0.15f, mOpacity ) ); 148 | } 149 | mAlphaTextures[i].enableAndBind(); 150 | gl::drawSolidRect( mAlphaRects[i] ); 151 | mAlphaTextures[i].disable(); 152 | } 153 | } 154 | 155 | float AlphaChooser::getHeight() 156 | { 157 | return mFullRect.getHeight(); 158 | } 159 | 160 | -------------------------------------------------------------------------------- /src/Buttons.h: -------------------------------------------------------------------------------- 1 | // 2 | // Buttons.h 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 5/17/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #pragma once 10 | #include "cinder/gl/Texture.h" 11 | #include "BloomNode.h" 12 | 13 | // toggle button is either on or off (e.g. show orbits) 14 | class ToggleButton : public BloomNode { 15 | public: 16 | 17 | ToggleButton( const int &buttonId, 18 | const bool &on, 19 | const ci::gl::Texture &texture, 20 | const ci::Area &onTextureArea, 21 | const ci::Area &offTextureArea ): 22 | BloomNode(buttonId), 23 | mOn(on), 24 | mTexture(texture), 25 | mOnTextureArea(onTextureArea), 26 | mOffTextureArea(offTextureArea) {} 27 | 28 | ~ToggleButton() {} 29 | 30 | virtual bool touchBegan(ci::app::TouchEvent::Touch touch); 31 | virtual bool touchEnded(ci::app::TouchEvent::Touch touch); 32 | virtual void draw(); 33 | 34 | bool isOn() { return mOn; } 35 | void setOn(bool on) { mOn = on; } 36 | 37 | void setRect(const ci::Rectf &rect) { mRect = rect; } 38 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 39 | const ci::Rectf& getRect() const { return mRect; } 40 | 41 | protected: 42 | 43 | bool mOn; 44 | ci::Area mOnTextureArea, mOffTextureArea; 45 | ci::gl::Texture mTexture; 46 | ci::Rectf mRect; 47 | }; 48 | 49 | // simple button is either being pressed or not (e.g. next, prev) 50 | class SimpleButton : public BloomNode { 51 | public: 52 | 53 | SimpleButton( const int &buttonId, 54 | const ci::gl::Texture &texture, 55 | const ci::Area &downTextureArea, 56 | const ci::Area &upTextureArea ): 57 | BloomNode(buttonId), 58 | mTexture(texture), 59 | mDownTextureArea(downTextureArea), 60 | mUpTextureArea(upTextureArea), 61 | mDownCount(0) {} 62 | 63 | ~SimpleButton() {} 64 | 65 | virtual bool touchBegan(ci::app::TouchEvent::Touch touch); 66 | virtual bool touchEnded(ci::app::TouchEvent::Touch touch); 67 | virtual void draw(); 68 | 69 | void setRect(const ci::Rectf &rect) { mRect = rect; } 70 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 71 | const ci::Rectf& getRect() const { return mRect; } 72 | 73 | protected: 74 | 75 | int mDownCount; 76 | ci::Area mUpTextureArea, mDownTextureArea; 77 | ci::gl::Texture mTexture; 78 | ci::Rectf mRect; 79 | 80 | }; 81 | 82 | // two-state button is either being pressed or not and has two possible states (e.g. play/pause) 83 | class TwoStateButton : public BloomNode { 84 | public: 85 | 86 | TwoStateButton( const int &buttonId, 87 | const bool &on, 88 | const ci::gl::Texture &texture, 89 | const ci::Area &offDownTextureArea, 90 | const ci::Area &offUpTextureArea, 91 | const ci::Area &onDownTextureArea, 92 | const ci::Area &onUpTextureArea ): 93 | BloomNode(buttonId), 94 | mOn(on), 95 | mTexture(texture), 96 | mDownCount(0), 97 | mOnDownTextureArea(onDownTextureArea), 98 | mOnUpTextureArea(onUpTextureArea), 99 | mOffDownTextureArea(offDownTextureArea), 100 | mOffUpTextureArea(offUpTextureArea) {} 101 | 102 | ~TwoStateButton() {} 103 | 104 | bool isOn() { return mOn; } 105 | void setOn(bool on) { mOn = on; } 106 | 107 | virtual bool touchBegan(ci::app::TouchEvent::Touch touch); 108 | virtual bool touchEnded(ci::app::TouchEvent::Touch touch); 109 | virtual void draw(); 110 | 111 | void setRect(const ci::Rectf &rect) { mRect = rect; } 112 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 113 | const ci::Rectf& getRect() const { return mRect; } 114 | 115 | protected: 116 | 117 | int mDownCount; 118 | bool mOn; 119 | ci::Area mOnUpTextureArea, mOnDownTextureArea, mOffUpTextureArea, mOffDownTextureArea; 120 | ci::gl::Texture mTexture; 121 | ci::Rectf mRect; 122 | 123 | }; 124 | 125 | // three-state button has three possible states (e.g. play/pause) 126 | // FIXME: just use an array of texture areas and make it a MultiStateButton 127 | class ThreeStateButton : public BloomNode { 128 | public: 129 | 130 | ThreeStateButton( const int &buttonId, 131 | const int &state, 132 | const ci::gl::Texture &texture, 133 | const ci::Area &firstTextureArea, 134 | const ci::Area &secondTextureArea, 135 | const ci::Area &thirdTextureArea ): 136 | BloomNode(buttonId), 137 | mState(state), 138 | mTexture(texture), 139 | mFirstTextureArea(firstTextureArea), 140 | mSecondTextureArea(secondTextureArea), 141 | mThirdTextureArea(thirdTextureArea) {} 142 | 143 | ~ThreeStateButton() {} 144 | 145 | int getState() const { return mState; } 146 | void setState(const int &state) { mState = state; } 147 | 148 | virtual bool touchBegan(ci::app::TouchEvent::Touch touch); 149 | virtual bool touchEnded(ci::app::TouchEvent::Touch touch); 150 | virtual void draw(); 151 | 152 | void setRect(const ci::Rectf &rect) { mRect = rect; } 153 | void setRect(const float &x1, const float &y1, const float &x2, const float &y2) { mRect.set(x1,y1,x2,y2); } 154 | const ci::Rectf& getRect() const { return mRect; } 155 | 156 | protected: 157 | 158 | int mState; 159 | ci::Area mFirstTextureArea, mSecondTextureArea, mThirdTextureArea; 160 | ci::gl::Texture mTexture; 161 | ci::Rectf mRect; 162 | 163 | }; 164 | -------------------------------------------------------------------------------- /src/ParticleController.cpp: -------------------------------------------------------------------------------- 1 | #include "cinder/app/AppBasic.h" 2 | #include "cinder/Rand.h" 3 | #include "cinder/Vector.h" 4 | #include "ParticleController.h" 5 | #include "Globals.h" 6 | 7 | using namespace ci; 8 | using std::list; 9 | 10 | ParticleController::ParticleController() 11 | { 12 | mPrevTotalParticleVertices = -1; 13 | mParticleVerts = NULL; 14 | 15 | mPrevTotalDustVertices = -1; 16 | mDustVerts = NULL; 17 | 18 | mBbRight = Vec3f::xAxis(); 19 | mBbUp = Vec3f::yAxis(); 20 | } 21 | 22 | void ParticleController::update( const Vec3f &camEye, float radius, const Vec3f &bbRight, const Vec3f &bbUp ) 23 | { 24 | mBbRight = bbRight; 25 | mBbUp = bbUp; 26 | 27 | for( list::iterator p = mParticles.begin(); p != mParticles.end(); ++p ){ 28 | p->update( radius, mBbRight, mBbUp ); 29 | } 30 | 31 | bool isGalaxyDust = false; 32 | if( G_ZOOM < G_ARTIST_LEVEL - 0.5f ) { // pass in as arguments to avoid global dependencies 33 | isGalaxyDust = true; 34 | } 35 | 36 | for( list::iterator d = mDusts.begin(); d != mDusts.end(); ++d ){ 37 | d->update( camEye ); 38 | } 39 | } 40 | 41 | 42 | void ParticleController::buildParticleVertexArray( float scaleOffset, Color c, float eclipseStrength ) 43 | { 44 | // Vec3f lookVec = mBbRight.cross( mBbUp ) * 0.025f; 45 | 46 | mTotalParticleVertices = mParticles.size() * 6; 47 | 48 | if (mTotalParticleVertices != mPrevTotalParticleVertices) { 49 | if( mParticleVerts != NULL ) { 50 | delete[] mParticleVerts; 51 | } 52 | mParticleVerts = new ParticleVertex[mTotalParticleVertices]; 53 | mPrevTotalParticleVertices = mTotalParticleVertices; 54 | } 55 | 56 | const float u1 = 0.0f; 57 | const float u2 = 1.0f; 58 | const float v1 = 0.0f; 59 | const float v2 = 1.0f; 60 | 61 | int vIndex = 0; 62 | 63 | for( list::iterator it = mParticles.begin(); it != mParticles.end(); ++it ){ 64 | 65 | Vec3f pos = it->mPos;// + lookVec; 66 | float radius = it->mRadius * ( 1.0f - it->mAgePer ) * scaleOffset;// * eclipseStrength;// * sin( it->mAgePer * M_PI ); 67 | float alpha = constrain(it->mAgePer * eclipseStrength, 0.0f, 1.0f); 68 | 69 | // Vec3f right = mBbRight * radius * it->mQuat; 70 | // Vec3f up = mBbUp * radius * it->mQuat; 71 | 72 | Vec3f right = Vec3f::yAxis() * radius * it->mQuat; 73 | Vec3f up = Vec3f::xAxis() * radius * it->mQuat; 74 | 75 | Vec3f p1 = pos - right - up; 76 | Vec3f p2 = pos + right - up; 77 | Vec3f p3 = pos - right + up; 78 | Vec3f p4 = pos + right + up; 79 | 80 | Vec4f col(c.r, c.g, c.b, alpha); 81 | 82 | mParticleVerts[vIndex].vertex = p1; 83 | mParticleVerts[vIndex].texture = Vec2f(u1,v1); 84 | mParticleVerts[vIndex].color = col; 85 | vIndex++; 86 | 87 | mParticleVerts[vIndex].vertex = p2; 88 | mParticleVerts[vIndex].texture = Vec2f(u2,v1); 89 | mParticleVerts[vIndex].color = col; 90 | vIndex++; 91 | 92 | mParticleVerts[vIndex].vertex = p3; 93 | mParticleVerts[vIndex].texture = Vec2f(u1,v2); 94 | mParticleVerts[vIndex].color = col; 95 | vIndex++; 96 | 97 | mParticleVerts[vIndex].vertex = p2; 98 | mParticleVerts[vIndex].texture = Vec2f(u2,v1); 99 | mParticleVerts[vIndex].color = col; 100 | vIndex++; 101 | 102 | mParticleVerts[vIndex].vertex = p3; 103 | mParticleVerts[vIndex].texture = Vec2f(u1,v2); 104 | mParticleVerts[vIndex].color = col; 105 | vIndex++; 106 | 107 | mParticleVerts[vIndex].vertex = p4; 108 | mParticleVerts[vIndex].texture = Vec2f(u2,v2); 109 | mParticleVerts[vIndex].color = col; 110 | vIndex++; 111 | } 112 | } 113 | 114 | void ParticleController::buildDustVertexArray( float scaleOffset, Node *node, float pinchAlphaPer, float dustAlpha ) 115 | { 116 | mTotalDustVertices = mDusts.size(); 117 | 118 | if (mTotalDustVertices != mPrevTotalDustVertices) { 119 | if (mDustVerts != NULL) { 120 | delete[] mDustVerts; 121 | } 122 | mDustVerts = new DustVertex[mTotalDustVertices]; 123 | mPrevTotalDustVertices = mTotalDustVertices; 124 | } 125 | 126 | int vIndex = 0; 127 | float alpha = dustAlpha * pinchAlphaPer; 128 | Color col; 129 | 130 | if (node) { 131 | col = node->mGlowColor; 132 | } 133 | 134 | for( list::iterator it = mDusts.begin(); it != mDusts.end(); ++it ){ 135 | mDustVerts[vIndex].vertex = it->mPos; //0.7f 136 | mDustVerts[vIndex].color = Vec4f(col.r, col.g, col.b, alpha * it->mAgePer); 137 | vIndex++; 138 | } 139 | } 140 | 141 | 142 | void ParticleController::drawParticleVertexArray( Node *node, float multi ) 143 | { 144 | // PARTICLES 145 | glEnableClientState( GL_VERTEX_ARRAY ); 146 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 147 | glEnableClientState( GL_COLOR_ARRAY ); 148 | 149 | glVertexPointer( 3, GL_FLOAT, sizeof(ParticleVertex), mParticleVerts ); 150 | glTexCoordPointer( 2, GL_FLOAT, sizeof(ParticleVertex), &mParticleVerts[0].texture ); 151 | glColorPointer( 4, GL_FLOAT, sizeof(ParticleVertex), &mParticleVerts[0].color ); 152 | 153 | glPushMatrix(); 154 | if( node ){ 155 | gl::translate( node->mPos ); 156 | float radius = node->mRadius * multi + 0.007f; 157 | gl::scale( Vec3f( radius, radius, radius ) ); 158 | } 159 | glDrawArrays( GL_TRIANGLES, 0, mTotalParticleVertices ); 160 | glPopMatrix(); 161 | 162 | glDisableClientState( GL_VERTEX_ARRAY ); 163 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 164 | glDisableClientState( GL_COLOR_ARRAY ); 165 | } 166 | 167 | void ParticleController::drawDustVertexArray( Node *node, float multi ) 168 | { 169 | // DUST 170 | glEnableClientState( GL_VERTEX_ARRAY ); 171 | glEnableClientState( GL_COLOR_ARRAY ); 172 | glVertexPointer( 3, GL_FLOAT, sizeof(DustVertex), mDustVerts ); 173 | glColorPointer( 4, GL_FLOAT, sizeof(DustVertex), &mDustVerts[0].color ); 174 | 175 | glPushMatrix(); 176 | if( node ) { 177 | gl::translate( node->mPos ); 178 | float radius = node->mRadius * multi + 0.007f; 179 | gl::scale( Vec3f( radius, radius, radius ) ); 180 | } 181 | glDrawArrays( GL_POINTS, 0, mTotalDustVertices ); 182 | glPopMatrix(); 183 | 184 | glDisableClientState( GL_VERTEX_ARRAY ); 185 | glDisableClientState( GL_COLOR_ARRAY ); 186 | } 187 | 188 | void ParticleController::addDusts( int amt ) 189 | { 190 | for( int i=0; i= 0) { 39 | mTextureProgressDest = prop; 40 | } 41 | else { 42 | // reset with negative values 43 | mTextureProgress = 0.0; 44 | mTextureProgressDest = 0.0; 45 | } 46 | } 47 | 48 | void LoadingScreen::setArtistProgress( float prop ) 49 | { 50 | if (prop >= 0) { 51 | mArtistProgressDest = prop; 52 | } 53 | else { 54 | // reset with negative values 55 | mArtistProgress = 0.0; 56 | mArtistProgressDest = 0.0; 57 | } 58 | } 59 | 60 | void LoadingScreen::setPlaylistProgress( float prop ) 61 | { 62 | if (prop >= 0) { 63 | mPlaylistProgressDest = prop; 64 | } 65 | else { 66 | // reset with negative values 67 | mPlaylistProgress = 0.0; 68 | mPlaylistProgressDest = 0.0; 69 | } 70 | } 71 | 72 | void LoadingScreen::update() 73 | { 74 | mTextureProgress += (mTextureProgressDest - mTextureProgress) * 0.2f; 75 | if ( fabs(mTextureProgress - mTextureProgressDest) < 0.001f ) { 76 | mTextureProgress = mTextureProgressDest; 77 | } 78 | mArtistProgress += (mArtistProgressDest - mArtistProgress) * 0.2f; 79 | if ( fabs(mArtistProgress - mArtistProgressDest) < 0.001f ) { 80 | mArtistProgress = mArtistProgressDest; 81 | } 82 | mPlaylistProgress += (mPlaylistProgressDest - mPlaylistProgress) * 0.2f; 83 | if ( fabs(mPlaylistProgress - mPlaylistProgressDest) < 0.001f ) { 84 | mPlaylistProgress = mPlaylistProgressDest; 85 | } 86 | mInterfaceSize = getRoot()->getInterfaceSize(); 87 | } 88 | 89 | bool LoadingScreen::isComplete() 90 | { 91 | bool textureProgressComplete = fabs(mTextureProgress - mTextureProgressDest) < 0.01f; 92 | bool artistProgressComplete = fabs(mArtistProgress - mArtistProgressDest) < 0.01f; 93 | bool playlistProgressComplete = fabs(mPlaylistProgress - mPlaylistProgressDest) < 0.01f; 94 | return textureProgressComplete && artistProgressComplete && playlistProgressComplete; 95 | } 96 | 97 | void LoadingScreen::draw() 98 | { 99 | Vec2f pos; 100 | float radius; 101 | 102 | Vec2f center = mInterfaceSize * 0.5f; 103 | gl::color( Color::white() ); 104 | 105 | //float fadeInAlpha = constrain( app::getElapsedFrames()/30.0f - 1.0f, 0.0f, 1.0f ); 106 | 107 | // BACKGROUND 108 | mBackgroundTex.enableAndBind(); 109 | Vec2f v1( center - mBackgroundTex.getSize() * 0.5f ); 110 | Vec2f v2( v1 + mBackgroundTex.getSize() ); 111 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f ) ); 112 | gl::drawSolidRect( Rectf( v1, v2 ) ); 113 | mBackgroundTex.disable(); 114 | 115 | 116 | gl::enableAdditiveBlending(); 117 | 118 | 119 | // PLANETARY TEXT 120 | mPlanetaryTex.enableAndBind(); 121 | float h = mPlanetaryTex.getHeight(); 122 | v1 = Vec2f( center.x + 60.0f, center.y-h*0.5f ); 123 | v2 = v1 + mPlanetaryTex.getSize(); 124 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f ) ); 125 | gl::drawSolidRect( Rectf( v1, v2 ) ); 126 | mPlanetaryTex.disable(); 127 | 128 | 129 | // STARGLOW 130 | mStarGlowTex.enableAndBind(); 131 | Vec2f starSize = mStarGlowTex.getSize() * Rand::randFloat( 0.75f, 0.85f ); 132 | v1 = center - starSize; 133 | v2 = v1 + starSize * 2.0f; 134 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 0.2f ) ); 135 | gl::drawSolidRect( Rectf( v1, v2 ) ); 136 | mStarGlowTex.disable(); 137 | 138 | 139 | gl::enableAlphaBlending(); 140 | 141 | mPlanetTex.enableAndBind(); 142 | 143 | // TINY PLANET 144 | float speed = app::getElapsedFrames() * 0.014f - M_PI_2; 145 | float sinAmt = sin( speed ); 146 | float cosAmt = cos( speed ); 147 | if( cosAmt > 0.0f ){ 148 | pos = Vec2f( sinAmt * 500.0f, 0.0f ); 149 | radius = 6.0f; 150 | v1 = center + pos - Vec2f( radius, radius ); 151 | v2 = v1 + Vec2f( radius, radius ) * 2.0f; 152 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f ) ); 153 | gl::drawSolidRect( Rectf( v1, v2 ) ); 154 | } 155 | 156 | // SMALL PLANET 157 | speed = app::getElapsedFrames() * 0.01f - M_PI_2; 158 | sinAmt = sin( speed ); 159 | cosAmt = cos( speed ); 160 | if( cosAmt > 0.0f ){ 161 | pos = Vec2f( sinAmt * 700.0f, 0.0f ); 162 | radius = 25.0f; 163 | v1 = center + pos - Vec2f( radius, radius ); 164 | v2 = v1 + Vec2f( radius, radius ) * 2.0f; 165 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f ) ); 166 | gl::drawSolidRect( Rectf( v1, v2 ) ); 167 | } 168 | 169 | // MEDIUM PLANET 170 | speed = app::getElapsedFrames() * 0.005f - M_PI_4; 171 | sinAmt = sin( speed ); 172 | cosAmt = cos( speed ); 173 | if( cosAmt > 0.0f ){ 174 | pos = Vec2f( sinAmt * 700.0f, 0.0f ); 175 | radius = 50.0f; 176 | v1 = center + pos - Vec2f( radius, radius ); 177 | v2 = v1 + Vec2f( radius, radius ) * 2.0f; 178 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f ) ); 179 | gl::drawSolidRect( Rectf( v1, v2 ) ); 180 | } 181 | 182 | // LARGE PLANET 183 | speed = app::getElapsedFrames() * 0.004f - M_PI_4; 184 | sinAmt = sin( speed ); 185 | cosAmt = cos( speed ); 186 | if( cosAmt > 0.0f ){ 187 | pos = Vec2f( sinAmt * 1500.0f, 0.0f ); 188 | radius = 300.0f; 189 | v1 = center + pos - Vec2f( radius, radius ); 190 | v2 = v1 + Vec2f( radius, radius ) * 2.0f; 191 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f ) ); 192 | gl::drawSolidRect( Rectf( v1, v2 ) ); 193 | } 194 | 195 | /* 196 | // LARGE PLANET 197 | v1 = Vec2f( center - Vec2f( mPlanetTex.getWidth(), mPlanetTex.getHeight() * 0.5f ) + Vec2f( app::getElapsedFrames() * 0.25f - 50.0f, 0.0f ) ); 198 | v2 = v1 + mPlanetTex.getSize(); 199 | gl::color( ColorA( 1.0f, 1.0f, 1.0f, 1.0f ) ); 200 | gl::drawSolidRect( Rectf( v1, v2 ) ); 201 | */ 202 | mPlanetTex.disable(); 203 | 204 | float barHeight = 2.0f; 205 | gl::color( BLUE ); 206 | gl::drawSolidRect( Rectf( 0, mInterfaceSize.y - barHeight * 3.0f, mInterfaceSize.x * mTextureProgress, mInterfaceSize.y - barHeight * 2.0f ) ); 207 | gl::color( BRIGHT_BLUE ); 208 | gl::drawSolidRect( Rectf( 0, mInterfaceSize.y - barHeight * 2.0f, mInterfaceSize.x * mArtistProgress, mInterfaceSize.y - barHeight * 1.0f ) ); 209 | gl::color( BRIGHT_YELLOW ); 210 | gl::drawSolidRect( Rectf( 0, mInterfaceSize.y - barHeight * 1.0f, mInterfaceSize.x * mPlaylistProgress, mInterfaceSize.y - barHeight * 0.0f ) ); 211 | } 212 | -------------------------------------------------------------------------------- /src/Node.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Node.h 3 | * Kepler 4 | * 5 | * Created by Robert Hodgin on 2/25/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include "cinder/Vector.h" 15 | #include "cinder/Color.h" 16 | #include "cinder/Font.h" 17 | #include "cinder/gl/Texture.h" 18 | #include "cinder/Sphere.h" 19 | #include "cinder/Camera.h" 20 | #include "BloomSphere.h" 21 | #include "OrbitRing.h" 22 | #include "PlanetRing.h" 23 | #include "TaskQueue.h" 24 | 25 | using bloom::BloomSphere; 26 | 27 | class Node { 28 | public: 29 | 30 | Node( Node *parent, int index, const ci::Font &font, const ci::Font &smallFont, const ci::Surface &hiResSurfaces, const ci::Surface &loResSurfaces, const ci::Surface &noAlbumArt ); 31 | 32 | virtual ~Node() 33 | { 34 | if (!UiTaskQueue::isTaskComplete(mTaskId)) { 35 | // std::cout << "canceling request for name rendering #" << mTaskId << std::endl; 36 | UiTaskQueue::cancelTask(mTaskId); 37 | } 38 | for( std::vector::iterator nodeIt = mChildNodes.begin(); nodeIt != mChildNodes.end(); ++nodeIt ){ 39 | delete (*nodeIt); 40 | } 41 | mChildNodes.clear(); 42 | } 43 | 44 | // METHODS 45 | void setSphereData( BloomSphere *hiSphere, BloomSphere *mdSphere, BloomSphere *loSphere, BloomSphere *tySphere ); 46 | virtual void update( float param1, float param2 ); 47 | virtual void updateGraphics( const ci::CameraPersp &cam, const ci::Vec2f ¢er, const ci::Vec3f &bbRight, const ci::Vec3f &bbUp, const float &w, const float &h ); 48 | virtual void drawEclipseGlow(); 49 | virtual void drawStarGlow( const ci::Vec3f &camEye, const ci::Vec3f &camNormal, const ci::gl::Texture &tex ){}; 50 | virtual void drawPlanet( const ci::gl::Texture &tex ) {}; 51 | virtual void drawExtraGlow( const ci::Vec3f &camEye, const ci::gl::Texture &texGlow, const ci::gl::Texture &texCore ) {}; 52 | virtual void drawClouds( const std::vector< ci::gl::Texture> &clouds ) {}; 53 | virtual void drawAtmosphere( const ci::Vec3f &camEye, const ci::Vec2f ¢er, const ci::gl::Texture &tex, const ci::gl::Texture &directionalTex, float pinchAlphaPer, float scaleSliderOffset ) {}; 54 | virtual void drawRings( const ci::gl::Texture &tex, const PlanetRing &planetRing, float camZPos ); 55 | virtual void findShadows( float camAlpha ) {}; 56 | virtual void drawOrbitRing( float pinchAlphaOffset, float camAlpha, const OrbitRing &orbitRing, float fadeInAlphaToArtist, float fadeInArtistToAlbum ); 57 | 58 | void drawName( const ci::CameraPersp &cam, float pinchAlphaOffset, float angle ); 59 | void wasTapped(){ mIsTapped = true; mHighlightStrength = 1.0f; } 60 | void drawTouchHighlight( float zoomAlpha ); 61 | void checkForNameTouch( std::vector &nodes, const ci::Vec2f &pos ); 62 | 63 | void setIsDying( bool isDying ); 64 | bool isDying() { return mIsDying; } 65 | bool isDead() { return mIsDead; } 66 | 67 | virtual bool isMostPlayed(){ return false; } 68 | virtual float getReleaseYear(){ return 0.0f; }; 69 | virtual int getTrackNumber(){ return -1; }; 70 | 71 | virtual void select(); 72 | void deselect(); 73 | 74 | virtual std::string getName()=0; // Name of the node *must* be provided by subclasses 75 | virtual uint64_t getId()=0; // ID of the node *must* be provided by subclasses 76 | 77 | // TODO: clean up interface and enable privates! 78 | //private: 79 | 80 | int mGen; 81 | int mIndex; 82 | Node *mParentNode; 83 | std::vector mChildNodes; 84 | 85 | // POSITION/VELOCITY 86 | ci::Vec3f mPos; // global position 87 | ci::Vec3f mPosDest; // artist node final position 88 | ci::Vec3f mAcc; // acceleration used for initial repulsion 89 | ci::Vec2f mScreenPos; // screen position 90 | ci::Vec3f mRelPos; // relative position 91 | ci::Vec3f mVel; // velocity based on mPos for helping the camera 92 | ci::Vec3f mBbRight, mBbUp; 93 | 94 | // CHARACTERISTICS 95 | 96 | // RADII 97 | float mRadiusInit; // Radius + input from slider 98 | float mRadius; // Radius of the Node 99 | float mInvRadius; // 1.0f/radius 100 | float mRadiusDest; // Destination radius 101 | float mGlowRadius; // Radius of the glow image 102 | 103 | // ORBIT 104 | float mOrbitAngle; // Current angle in relation to the parentNode 105 | float mOrbitStartAngle; 106 | float mOrbitRadiusMin; 107 | float mOrbitRadiusMax; 108 | float mOrbitRadius; // Current distance from parentNode 109 | float mOrbitRadiusDest; // Final distance from parentNode 110 | float mOrbitPeriod; // Time in seconds to orbit parentNode 111 | 112 | // ROTATION 113 | float mAngularVelocity; // Change in angle per frame 114 | ci::Vec3f mAxialRot; 115 | float mAxialTilt; // Planetary axis 116 | float mAxialVel; // Speed of rotation around mAxialTilt axis; 117 | 118 | // DIST FROM CAMERA 119 | float mDistFromCamZAxis; // Node's distance from Cam eye 120 | float mPrevDistFromCamZAxis; // Node's previous distance from Cam eye 121 | float mDistFromCamZAxisPer; // normalized range. 122 | ci::Vec2f mScreenDirToCenter; // Direction from screenpos to center 123 | float mScreenDistToCenterPer; 124 | 125 | // MUSIC LIB DATA 126 | float mPercentPlayed; // Track: percent of playback (perhaps this can be pulled directly from player?) 127 | float mHighestPlayCount; // Album: used to normalize track playcount data 128 | float mLowestPlayCount; // Album: used to normalize track playcount data 129 | std::string mGenre; // Genre 130 | 131 | float mZoomPer; // 0.0 to 1.0 based on G_ZOOM vs mGen 132 | 133 | int mPlanetTexIndex; // Which of the planet textures is used 134 | int mCloudTexIndex; // Which of the cloud textures is used 135 | float mIdealCameraDist; // Ideal distance from node to camera 136 | 137 | // NAME 138 | ci::Font mFont, mSmallFont; 139 | ci::gl::Texture mNameTex; // Texture of the name 140 | float mHashPer; // Unique 0.0 to 1.0 from artist name 141 | ci::Surface mHighResSurfaces; // Images for Track moon surface 142 | ci::Surface mLowResSurfaces; // Images for Track moon surface 143 | ci::Surface mNoAlbumArtSurface; 144 | ci::Rectf mHitArea; // name hit area 145 | ci::Rectf mSphereHitArea; // node hit area 146 | 147 | ci::Sphere mSphere; 148 | float mSphereScreenRadius;// mSphere radius in screenspace 149 | 150 | 151 | // COLORS 152 | float mHue; 153 | float mSat; 154 | float mVal; 155 | ci::Color mColor; // Color of the node 156 | ci::Color mGlowColor; // Color of the star glow 157 | ci::Color mEclipseColor; // Color during eclipse 158 | float mEclipseStrength; // Strength of the eclipse (0, no occlusion. 1, full occlusion) 159 | float mEclipseAngle; // screenspace angle of eclipse effect 160 | float mEclipseDirBasedAlpha; // The alpha of the directional eclipse effect based on screenspace distance 161 | float mClosenessFadeAlpha; // makes objects fade out if they are too close to the camera. prevents clipping poops 162 | int mAge; 163 | int mDeathCount; 164 | int mDeathThresh; 165 | float mDeathPer; 166 | int mBirthPause; 167 | bool mIsTapped; // Highlight when tapped 168 | float mHighlightStrength; // Falloff for the highlight glow 169 | bool mIsSelected; // Node has been chosen 170 | bool mIsHighlighted; // Node is able to be chosen 171 | bool mIsPlaying; // Node represents something about the currently playing track (album/artist) 172 | 173 | protected: 174 | 175 | bool mIsDying; 176 | bool mIsDead; 177 | 178 | bool mNameTextureRequested; 179 | float mNameTexCreatedTime; 180 | float mLabelScale; 181 | uint64_t mTaskId; 182 | void createNameSurface(); 183 | void createNameTexture( ci::Surface8u nameSurface ); 184 | 185 | 186 | // SPHERE DATA (owned by World) 187 | BloomSphere *mHiSphere; 188 | BloomSphere *mMdSphere; 189 | BloomSphere *mLoSphere; 190 | BloomSphere *mTySphere; 191 | }; -------------------------------------------------------------------------------- /src/HelpLayer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * UiLayer.cpp 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 2/7/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | #include "HelpLayer.h" 11 | #include "cinder/Text.h" 12 | #include "cinder/gl/gl.h" 13 | #include "cinder/Color.h" 14 | #include "cinder/Utilities.h" // for launchWebBrowser() 15 | #include "CinderFlurry.h" // for logging 16 | #include "Globals.h" // for color constants 17 | #include "BloomScene.h" // for getRoot() functionality (FIXME) 18 | #include "StringHelpers.h" // for string/wstring UTF8/UTF32 conversion 19 | 20 | using namespace pollen::flurry; 21 | using namespace ci; 22 | using namespace ci::app; 23 | using namespace std; 24 | 25 | void HelpLayer::setup( const ci::Font &smallFont, const ci::Font &bigFont, const ci::Font &bigBoldFont ) 26 | { 27 | mSmallFont = smallFont; 28 | mBigFont = bigFont; 29 | mBigBoldFont = bigBoldFont; 30 | mInterfaceSize = Vec2f::zero(); 31 | 32 | /////////// 33 | 34 | // use TextLayouts for multicolored text runs... 35 | 36 | TextLayout layout; 37 | layout.setColor( Color::white() ); 38 | layout.setFont( mBigBoldFont ); 39 | layout.addLine( "Planetary" ); 40 | layout.setFont( mBigFont ); 41 | layout.append( " by " ); 42 | layout.setFont( mBigBoldFont ); 43 | layout.append( "bloom." ); 44 | mHeadingTex = layout.render( true, false ); 45 | 46 | layout = TextLayout(); 47 | layout.setColor( BRIGHT_BLUE ); 48 | layout.setFont( mSmallFont ); 49 | layout.addLine( "© 2011 Bloom Studio, Inc. All Rights Reserved. Made with " ); 50 | layout.setColor( Color::white() ); 51 | layout.append("Cinder"); 52 | layout.setColor( BRIGHT_BLUE ); 53 | layout.append(". Questions? Comments? "); 54 | layout.setColor( Color::white() ); 55 | layout.append("Visit the website"); 56 | layout.setColor( BRIGHT_BLUE ); 57 | layout.append(" or "); 58 | layout.setColor( Color::white() ); 59 | layout.append("send us an email"); 60 | layout.setColor( BRIGHT_BLUE ); 61 | layout.append("." ); 62 | mBodyTex = layout.render( true, false ); 63 | 64 | /////////////////////// 65 | 66 | // calculate layout... 67 | 68 | const Vec2f padding(18,15); 69 | const float w = mInterfaceSize.x; // initally 0, see update() for correct value 70 | const float h = mHeadingTex.getHeight() + mBodyTex.getHeight() + (padding.y * 2); 71 | 72 | mHeadingPos = padding; 73 | mBodyPos = padding + Vec2f(0,mHeadingTex.getHeight()); 74 | mBgRect = Rectf( 0, 0, w, h ); 75 | 76 | // and animation... 77 | mAnimating = false; 78 | mShowing = false; 79 | mCurrentY = -h; 80 | mTargetY = -h; 81 | 82 | /////////////////////// 83 | 84 | // use TextBox to measure glyphs and generate hit areas... 85 | 86 | // make a wide string for counting characters (because © is double-wide) 87 | wstring bodyText = L"© 2011 Bloom Studio, Inc. All Rights Reserved. Made with Cinder. Questions? Comments? Visit the website or send us an email."; 88 | 89 | // make a normal string to pass to cinder text routines 90 | string strBodyText = bloom::wstringToUtf8( bodyText ); 91 | 92 | // TODO: use some sort of markup so that text doesn't have to be repeated 93 | // and then we can generate hit rects lazily on demand 94 | 95 | TextBox box; 96 | box.setFont( mSmallFont ); 97 | box.setText( strBodyText ); 98 | 99 | std::vector > glyphPositions = box.measureGlyphs(); 100 | 101 | // cout << strBodyText << endl; 102 | // cout << glyphPositions.size() << " glyph positions available" << endl; 103 | // cout << bodyText.size() << " characters in bodyText" << endl; 104 | // cout << strBodyText.size() << " characters in strBodyText" << endl; 105 | 106 | updateRect( &mCinderRect, bodyText, L"Cinder", glyphPositions ); 107 | updateRect( &mWebRect, bodyText, L"Visit the website", glyphPositions ); 108 | updateRect( &mEmailRect, bodyText, L"send us an email", glyphPositions ); 109 | 110 | mCinderRect.offset( mBodyPos ); 111 | mWebRect.offset( mBodyPos ); 112 | mEmailRect.offset( mBodyPos ); 113 | } 114 | 115 | void HelpLayer::updateRect( Rectf *rect, const std::wstring &fullStr, const std::wstring &rectStr, const std::vector > &glyphPositions ) 116 | { 117 | const size_t startIndex = fullStr.find(rectStr); 118 | const size_t endIndex = startIndex + rectStr.size(); 119 | 120 | // wcout << rectStr << L" length is: " << rectStr.size() << endl; 121 | 122 | // glyph the first 123 | uint16_t glyph = glyphPositions[startIndex].first; 124 | Vec2f pos = glyphPositions[startIndex].second; 125 | Rectf bbox = mSmallFont.getGlyphBoundingBox(glyph); 126 | // account for flipped axis: 127 | bbox.y1 *= -1.0f; 128 | bbox.y2 *= -1.0f; 129 | Rectf bounds = bbox.getOffset(pos); 130 | rect->set(bounds.x1, bounds.y1, bounds.x2, bounds.y2); 131 | 132 | // glyph the rest 133 | for (int i = startIndex + 1; i < endIndex; i++) { 134 | glyph = glyphPositions[i].first; 135 | pos = glyphPositions[i].second; 136 | bbox = mSmallFont.getGlyphBoundingBox(glyph); 137 | // account for flipped axis: 138 | bbox.y1 *= -1.0f; 139 | bbox.y2 *= -1.0f; 140 | rect->include( bbox.getOffset(pos) ); 141 | } 142 | } 143 | 144 | bool HelpLayer::touchBegan( TouchEvent::Touch touch ) 145 | { 146 | return mBgRect.contains( globalToLocal( touch.getPos() ) ); 147 | } 148 | 149 | bool HelpLayer::touchEnded( TouchEvent::Touch touch ) 150 | { 151 | Vec2f pos = globalToLocal( touch.getPos() ); 152 | 153 | // TODO: should we use a callback for these and handle the actions in the main app? 154 | 155 | Url mailToLink( "mailto:planetary@bloom.io?subject=Planetary feedback" ); 156 | Url planetaryWebsite( "http://planetary.bloom.io" ); 157 | // Url bloomWebsite( "http://bloom.io" ); 158 | Url cinderWebsite( "http://libcinder.org" ); 159 | 160 | const Vec2f linkPadding(5,5); 161 | 162 | if( mEmailRect.inflated( linkPadding ).contains( pos ) ){ 163 | // Flurry::getInstrumentation()->logEvent("Email Link Selected"); 164 | launchWebBrowser( mailToLink ); 165 | } else if( mWebRect.inflated( linkPadding ).contains( pos ) ){ 166 | // Flurry::getInstrumentation()->logEvent("Planetary Link Selected"); 167 | launchWebBrowser( planetaryWebsite ); 168 | 169 | // } else if( mBloomButton.inflated( linkPadding ).contains( pos ) ){ 170 | // Flurry::getInstrumentation()->logEvent("Bloom Link Selected"); 171 | // launchWebBrowser( bloomWebsite ); 172 | // 173 | } else if( mCinderRect.inflated( linkPadding ).contains( pos ) ){ 174 | // Flurry::getInstrumentation()->logEvent("Cinder Link Selected"); 175 | launchWebBrowser( cinderWebsite ); 176 | } 177 | 178 | return mBgRect.contains( pos ); 179 | } 180 | 181 | void HelpLayer::show( bool show, bool animate ) 182 | { 183 | mShowing = show; 184 | mAnimating = animate; 185 | if (mShowing) { 186 | mTargetY = 0.0f; 187 | // ensure we're visible 188 | setVisible(true); 189 | } 190 | else { 191 | mTargetY = -mBgRect.getHeight(); 192 | // don't set invisible yet, do that in update when we're done animating 193 | } 194 | } 195 | 196 | void HelpLayer::update() 197 | { 198 | mInterfaceSize = getRoot()->getInterfaceSize(); 199 | mBgRect.x2 = mInterfaceSize.x; 200 | 201 | if (mCurrentY != mTargetY) { 202 | if (mAnimating) { 203 | mCurrentY += (mTargetY - mCurrentY) * 0.2f; 204 | if (fabs(mCurrentY - mTargetY) < 0.01f) { 205 | mCurrentY = mTargetY; 206 | } 207 | } 208 | else { 209 | mCurrentY = mTargetY; 210 | } 211 | setTransform( Matrix44f::createTranslation( Vec3f(0, round(mCurrentY), 0) ) ); 212 | } 213 | else { 214 | if (!mShowing) { 215 | setVisible(false); 216 | } 217 | } 218 | } 219 | 220 | void HelpLayer::draw() 221 | { 222 | gl::color( Color::black() ); 223 | gl::drawSolidRect( mBgRect ); 224 | 225 | const float dragAlphaPer = min( pow( 1.0f - (fabs(mCurrentY) / mBgRect.getHeight()), 2.0f ), 1.0f ); 226 | gl::color( Color( dragAlphaPer, dragAlphaPer, dragAlphaPer ) ); 227 | gl::draw( mHeadingTex, mHeadingPos ); 228 | gl::draw( mBodyTex, mBodyPos ); 229 | 230 | gl::color( ColorA(BRIGHT_BLUE, 0.15f * dragAlphaPer) ); 231 | gl::drawLine( mBgRect.getLowerLeft(), mBgRect.getLowerRight() ); 232 | 233 | // gl::color( Color::white() ); 234 | // gl::drawStrokedRect( mCinderRect ); 235 | // gl::drawStrokedRect( mWebRect ); 236 | // gl::drawStrokedRect( mEmailRect ); 237 | 238 | glPushMatrix(); 239 | gl::translate( Vec2f(0, 2.0f) ); 240 | gl::color( ColorA(dragAlphaPer, dragAlphaPer, dragAlphaPer, 0.5f) ); 241 | gl::drawLine( mCinderRect.getLowerLeft(), mCinderRect.getLowerRight() ); 242 | gl::drawLine( mWebRect.getLowerLeft(), mWebRect.getLowerRight() ); 243 | gl::drawLine( mEmailRect.getLowerLeft(), mEmailRect.getLowerRight() ); 244 | glPopMatrix(); 245 | } 246 | -------------------------------------------------------------------------------- /src/SettingsPanel.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsPanel.cpp 3 | // Kepler 4 | // 5 | // Created by Tom Carden on 8/25/11. 6 | // Copyright 2013 Smithsonian Institution. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "SettingsPanel.h" 11 | #include "Globals.h" 12 | #include "BloomGl.h" // for batch drawing 13 | #include "BloomScene.h" // for mRoot 14 | 15 | using namespace ci; 16 | using namespace ci::app; 17 | using namespace std; 18 | 19 | void SettingsPanel::setup( const Vec2f &interfaceSize, ipod::Player *player, const Font &font, const gl::Texture &uiSmallButtonsTex ) 20 | { 21 | // create, add, and position everything... 22 | createChildren( font, uiSmallButtonsTex ); 23 | setInterfaceSize( interfaceSize ); 24 | 25 | // set initial state... 26 | setOrbitsOn( G_DRAW_RINGS ); 27 | setLabelsOn( G_DRAW_TEXT ); 28 | setHelpOn( false ); // this is the default in KeplerApp 29 | setDebugOn( G_DEBUG ); 30 | setShuffleOn( player->getShuffleMode() != ipod::Player::ShuffleModeOff ); 31 | setRepeatMode( player->getRepeatMode() ); 32 | 33 | if( G_IS_IPAD2 ) { 34 | setGyroOn( G_USE_GYRO ); 35 | } 36 | } 37 | 38 | void SettingsPanel::createChildren( const Font &font, const gl::Texture &uiSmallButtonsTex ) 39 | { 40 | // !!! SMALL BUTTONS !!! 41 | float x0 = 350.0f; 42 | float x1 = 390.0f; 43 | float x2 = 430.0f; 44 | float x3 = 470.0f; 45 | float x4 = 510.0f; 46 | 47 | float y0 = 300.0f; 48 | float y1 = 340.0f; 49 | float y2 = 380.0f; 50 | float y3 = 420.0f; 51 | float y4 = 460.0f; 52 | float y5 = 500.0f; 53 | 54 | 55 | mHelpButton = new ToggleButton( HELP, 56 | false, 57 | uiSmallButtonsTex, 58 | Area( x0, y1, x1, y2 ), // on texture 59 | Area( x0, y0, x1, y1 ) ); // off texture 60 | 61 | if( G_IS_IPAD2 ){ 62 | mGyroButton = new ToggleButton( USE_GYRO, 63 | false, 64 | uiSmallButtonsTex, 65 | Area( x1, y1, x2, y2 ), // on texture 66 | Area( x1, y0, x2, y1 ) ); // off texture 67 | } 68 | 69 | mOrbitsButton = new ToggleButton( DRAW_RINGS, 70 | false, 71 | uiSmallButtonsTex, 72 | Area( x2, y1, x3, y2 ), // on texture 73 | Area( x2, y0, x3, y1 ) ); // off texture 74 | 75 | mLabelsButton = new ToggleButton( DRAW_TEXT, 76 | false, 77 | uiSmallButtonsTex, 78 | Area( x3, y1, x4, y2 ), // on texture 79 | Area( x3, y0, x4, y1 ) ); // off texture 80 | 81 | mDebugButton = new ToggleButton( DEBUG_FEATURE, 82 | false, 83 | uiSmallButtonsTex, 84 | Area( x0, y3, x1, y4 ), // on texture 85 | Area( x0, y2, x1, y3 ) ); // off texture 86 | 87 | mScreensaverButton = new ToggleButton( AUTO_MOVE, 88 | false, 89 | uiSmallButtonsTex, 90 | Area( x1, y3, x2, y4 ), 91 | Area( x1, y2, x2, y3 ) ); 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | mShuffleButton = new ToggleButton( SHUFFLE, 101 | false, 102 | uiSmallButtonsTex, 103 | Area( x2, y3, x3, y4 ), // on texture 104 | Area( x2, y2, x3, y3 ) ); // off texture 105 | 106 | mRepeatButton = new ThreeStateButton( REPEAT, 107 | 0, 108 | uiSmallButtonsTex, 109 | Area( x3, y2, x4, y3 ), // first texture (off) 110 | Area( x3, y3, x4, y4 ), // second texture (repeat all) 111 | Area( x3, y4, x4, y5 ) ); // third texture (repeat one) 112 | 113 | /////// 114 | // TODO: add initial value 115 | mParamSlider1 = new Slider( PARAMSLIDER1, // ID 116 | uiSmallButtonsTex, 117 | Area( 351, 460, 358, 500 ), // bg texture 118 | Area( 362, 460, 369, 500 ), // fg texture 119 | Area( 390, 460, 430, 500 ), // thumb on texture 120 | Area( 430, 460, 470, 500 ) ); // thumb off texture 121 | 122 | mParamSlider1->setValue( 0.25f ); 123 | mParamSlider1Label = new TextLabel( NO_BUTTON, font, BRIGHT_BLUE ); 124 | mParamSlider1Label->setText( "Scale" ); 125 | 126 | mParamSlider2 = new Slider( PARAMSLIDER2, // ID 127 | uiSmallButtonsTex, 128 | Area( 351, 460, 358, 500 ), // bg texture 129 | Area( 362, 460, 369, 500 ), // fg texture 130 | Area( 390, 460, 430, 500 ), // thumb on texture 131 | Area( 430, 460, 470, 500 ) ); // thumb off texture 132 | 133 | mParamSlider2->setValue( 0.15f ); 134 | mParamSlider2Label = new TextLabel( NO_BUTTON, font, BRIGHT_BLUE ); 135 | mParamSlider2Label->setText( "Speed" ); 136 | } 137 | 138 | bool SettingsPanel::addedToScene() 139 | { 140 | // now mRoot is valid we can add children 141 | addChildren(); // FIXME: make it so you can add children even if mRoot is invalid 142 | return false; 143 | } 144 | 145 | void SettingsPanel::addChildren() 146 | { 147 | addChild( BloomNodeRef(mShuffleButton) ); 148 | addChild( BloomNodeRef(mRepeatButton) ); 149 | addChild( BloomNodeRef(mScreensaverButton) ); 150 | addChild( BloomNodeRef(mHelpButton) ); 151 | addChild( BloomNodeRef(mOrbitsButton) ); 152 | addChild( BloomNodeRef(mLabelsButton) ); 153 | // addChild( BloomNodeRef(mDebugButton) ); 154 | if( G_IS_IPAD2 ) addChild( BloomNodeRef(mGyroButton) ); 155 | addChild( BloomNodeRef(mParamSlider1) ); 156 | addChild( BloomNodeRef(mParamSlider2) ); 157 | addChild( BloomNodeRef(mParamSlider1Label) ); 158 | addChild( BloomNodeRef(mParamSlider2Label) ); 159 | } 160 | 161 | void SettingsPanel::setInterfaceSize( const Vec2f &interfaceSize ) 162 | { 163 | mInterfaceSize = interfaceSize; 164 | 165 | const float topBorder = 5.0f; 166 | const float sideBorder = 10.0f; 167 | const float bSizeSmall = 40.0f; 168 | const bool landscape = interfaceSize.x > interfaceSize.y; 169 | float y1 = topBorder; 170 | float y2 = y1 + bSizeSmall; 171 | 172 | // SHUFFLE TOGGLE BUTTON 173 | float x1 = interfaceSize.x - sideBorder - bSizeSmall - 3.0f; 174 | float x2 = x1 + bSizeSmall; 175 | mShuffleButton->setRect( x1, y1, x2, y2 ); 176 | 177 | // REPEAT TOGGLE BUTTON 178 | x1 -= bSizeSmall; 179 | x2 = x1 + bSizeSmall; 180 | mRepeatButton->setRect( x1, y1, x2, y2 ); 181 | 182 | // TEXT LABELS TOGGLE BUTTON 183 | float gap = landscape ? 110.0f : 35.0f; 184 | x1 -= bSizeSmall + gap; 185 | x2 = x1 + bSizeSmall; 186 | mLabelsButton->setRect( x1, y1, x2, y2 ); 187 | 188 | // ORBIT RING TOGGLE BUTTON 189 | x1 -= bSizeSmall; 190 | x2 = x1 + bSizeSmall; 191 | mOrbitsButton->setRect( x1, y1, x2, y2 ); 192 | 193 | // GYRO TOGGLE BUTTON 194 | if( G_IS_IPAD2 ){ 195 | x1 -= bSizeSmall; 196 | x2 = x1 + bSizeSmall; 197 | mGyroButton->setRect( x1, y1, x2, y2 ); 198 | } 199 | 200 | // DEBUG TOGGLE BUTTON 201 | // x1 -= bSizeSmall; 202 | // x2 = x1 + bSizeSmall; 203 | // mDebugButton->setRect( x1, y1, x2, y2 ); 204 | 205 | // SCREENSAVER TOGGLE BUTTON 206 | x1 -= bSizeSmall; 207 | x2 = x1 + bSizeSmall; 208 | mScreensaverButton->setRect( x1, y1, x2, y2 ); 209 | 210 | //// HELP TOGGLE BUTTON 211 | x1 -= bSizeSmall; 212 | x2 = x1 + bSizeSmall; 213 | mHelpButton->setRect( x1, y1, x2, y2 ); 214 | 215 | 216 | const float paramSliderWidth = landscape ? 200.0f : 120.0f; 217 | const float slider1X = 60.0f; 218 | const float slider2X = slider1X + paramSliderWidth + 75.0f; 219 | const float sliderYOff = 16.0f; 220 | const float sliderHeight = 20.0f; 221 | 222 | mParamSlider1->setRect( slider1X, sliderYOff, slider1X + paramSliderWidth, sliderYOff + sliderHeight ); 223 | mParamSlider2->setRect( slider2X, sliderYOff, slider2X + paramSliderWidth, sliderYOff + sliderHeight ); 224 | 225 | mParamSlider1Label->setRect( slider1X - 40.0f, sliderYOff, slider1X, sliderYOff + sliderHeight ); 226 | mParamSlider2Label->setRect( slider2X - 45.0f, sliderYOff, slider2X, sliderYOff + sliderHeight); 227 | } 228 | 229 | void SettingsPanel::update() 230 | { 231 | Vec2f interfaceSize = getRoot()->getInterfaceSize(); 232 | if ( mInterfaceSize != interfaceSize ) { 233 | setInterfaceSize( interfaceSize ); 234 | } 235 | } 236 | 237 | void SettingsPanel::deepDraw() 238 | { 239 | if (mVisible) { 240 | glPushMatrix(); 241 | glMultMatrixf(mTransform); 242 | 243 | // draw background so we can't see alpha/playlist chooser behind us in transitions 244 | gl::color( Color::black() ); 245 | gl::drawSolidRect( Rectf( Vec2f( 0.0f, 0.0f ), Vec2f( mInterfaceSize.x, getHeight() ) ) ); 246 | 247 | // draw line at the top (as for each ui panel) 248 | gl::color( ColorA( BRIGHT_BLUE, 0.125f ) ); 249 | gl::drawLine( Vec2f( 0.0f, 0.0f ), Vec2f( mInterfaceSize.x, 0.0f ) ); 250 | 251 | // tint children 252 | gl::color( ColorA( 1, 1, 1, mOpacity ) ); // mOpacity comes from UiLayer 253 | 254 | bloom::gl::beginBatch(); 255 | // draw children 256 | BOOST_FOREACH(BloomNodeRef child, mChildren) { 257 | child->deepDraw(); 258 | } 259 | bloom::gl::endBatch(); 260 | glPopMatrix(); 261 | } 262 | } 263 | 264 | //bool SettingsPanel::onBloomNodeTouchEnded( BloomNodeRef nodeRef ) 265 | //{ 266 | // if ( nodeRef->getId() > NO_BUTTON && nodeRef->getId() < LAST_BUTTON ) { 267 | // mCallbacksButtonPressed.call(ButtonId(nodeRef->getId())); 268 | // } 269 | // return false; 270 | //} 271 | 272 | float SettingsPanel::getHeight() 273 | { 274 | return 50.0f; 275 | } -------------------------------------------------------------------------------- /src/UiLayer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * UiLayer.cpp 3 | * Bloom 4 | * 5 | * Created by Robert Hodgin on 2/7/11. 6 | * Copyright 2013 Smithsonian Institution. All rights reserved. 7 | * 8 | */ 9 | 10 | 11 | #include "cinder/gl/gl.h" 12 | #include "UiLayer.h" 13 | #include "CinderFlurry.h" 14 | #include "Globals.h" 15 | #include "BloomGl.h" 16 | #include "BloomScene.h" 17 | 18 | using namespace pollen::flurry; 19 | using namespace ci; 20 | using namespace ci::app; 21 | using namespace std; 22 | 23 | void UiLayer::setup( PlaylistChooserRef playlistChooser, 24 | AlphaChooserRef alphaChooser, 25 | PlayControlsRef playControls, 26 | SettingsPanelRef settingsPanel, 27 | const gl::Texture &uiButtonsTex, 28 | const bool &showSettings, 29 | const Vec2f interfaceSize ) 30 | { 31 | mPlaylistChooser = playlistChooser; 32 | mAlphaChooser = alphaChooser; 33 | mPlayControls = playControls; 34 | mSettingsPanel = settingsPanel; 35 | 36 | mButtonsTex = uiButtonsTex; 37 | 38 | mIsPanelOpen = false; 39 | mIsPanelTabTouched = false; 40 | mHasPanelBeenDragged = false; 41 | 42 | // set now, needed in setShowSettings and updateLayout 43 | mInterfaceSize = interfaceSize; 44 | 45 | // these rectangles are essentially constant (except for width), movement is handled by setTransform 46 | mPanelTabRect = Rectf( interfaceSize.x - 200.0f, -42.0f, interfaceSize.x, 2.0f ); 47 | 48 | // make sure we're showing enough, then update layout 49 | setShowSettings(showSettings); 50 | 51 | updateLayout( interfaceSize ); 52 | } 53 | 54 | void UiLayer::setShowSettings( bool visible ) 55 | { 56 | mPanelOpenY = mInterfaceSize.y - getPanelHeight(); 57 | } 58 | 59 | void UiLayer::updateLayout( Vec2f interfaceSize ) 60 | { 61 | mPanelTabRect.x1 = interfaceSize.x - 200.0f; 62 | mPanelTabRect.x2 = interfaceSize.x; 63 | 64 | mPanelOpenY = interfaceSize.y - getPanelHeight(); 65 | mPanelClosedY = interfaceSize.y; 66 | 67 | // cancel interactions 68 | mIsPanelTabTouched = false; 69 | mHasPanelBeenDragged = false; 70 | 71 | // set dests for sub-panels 72 | mSettingsDestY = mPlayControls->getHeight(); 73 | mChooserDestY = mPlayControls->getHeight(); 74 | if ( isShowingFilter() ) { 75 | mSettingsDestY += max(mAlphaChooser->getHeight(), mPlaylistChooser->getHeight()); 76 | } 77 | 78 | // jump to end of animation 79 | if ( mIsPanelOpen ) { 80 | mPanelY = mPanelOpenY; 81 | mSettingsY = mSettingsDestY; 82 | mChooserY = mChooserDestY; 83 | } 84 | else { 85 | mPanelY = mPanelClosedY; 86 | } 87 | 88 | mInterfaceSize = interfaceSize; 89 | } 90 | 91 | bool UiLayer::touchBegan( TouchEvent::Touch touch ) 92 | { 93 | mHasPanelBeenDragged = false; 94 | 95 | Vec2f touchPos = globalToLocal( touch.getPos() ); 96 | 97 | mIsPanelTabTouched = mPanelTabRect.contains( touchPos ); 98 | 99 | if( mIsPanelTabTouched ){ 100 | // remember touch offset for accurate dragging 101 | mPanelTabTouchOffset = mPanelTabRect.getUpperLeft() - touchPos; 102 | } 103 | 104 | return mIsPanelTabTouched; 105 | } 106 | 107 | bool UiLayer::touchMoved( TouchEvent::Touch touch ) 108 | { 109 | Vec2f touchPos = globalToLocal( touch.getPos() ); 110 | 111 | if( mIsPanelTabTouched ){ 112 | mHasPanelBeenDragged = true; 113 | 114 | // apply the touch pos and offset 115 | Vec2f newPos = touchPos + mPanelTabTouchOffset; 116 | mPanelY += newPos.y - mPanelTabRect.y1; 117 | 118 | const float maxPanelY = mInterfaceSize.y - getPanelHeight(); 119 | mPanelY = constrain( mPanelY, maxPanelY, mPanelClosedY ); 120 | } 121 | 122 | return mIsPanelTabTouched; 123 | } 124 | 125 | bool UiLayer::touchEnded( TouchEvent::Touch touch ) 126 | { 127 | // decide if the open state should change: 128 | if( mIsPanelTabTouched ){ 129 | if( mHasPanelBeenDragged ){ 130 | mIsPanelOpen = fabs(mPanelY - mPanelOpenY) < fabs(mPanelY - mPanelClosedY); 131 | } 132 | else { 133 | mIsPanelOpen = !mIsPanelOpen; 134 | // if (mIsPanelOpen) { 135 | // Flurry::getInstrumentation()->logEvent("UIPanel Opened"); 136 | // } else { 137 | // Flurry::getInstrumentation()->logEvent("UIPanel Closed"); 138 | // } 139 | } 140 | } 141 | 142 | // reset for next time 143 | mIsPanelTabTouched = false; 144 | mHasPanelBeenDragged = false; 145 | 146 | return false; 147 | } 148 | 149 | void UiLayer::update() 150 | { 151 | Vec2f interfaceSize = getRoot()->getInterfaceSize(); 152 | // check for orientation change 153 | if( interfaceSize != mInterfaceSize ){ 154 | updateLayout( interfaceSize ); 155 | } 156 | 157 | if ( !mHasPanelBeenDragged ) { 158 | // if we're not dragging, animate to current state 159 | if( mIsPanelOpen ){ 160 | mPanelY += (mPanelOpenY - mPanelY) * 0.25f; 161 | } 162 | else { 163 | mPanelY += (mPanelClosedY - mPanelY) * 0.25f; 164 | } 165 | } 166 | 167 | mChooserY += (mChooserDestY - mChooserY) * 0.25f; 168 | mSettingsY += (mSettingsDestY - mSettingsY) * 0.25f; 169 | 170 | mPlaylistChooser->setTransform( Matrix44f::createTranslation( Vec3f(0, mChooserY, 0) ) ); 171 | mAlphaChooser->setTransform( Matrix44f::createTranslation( Vec3f(0, mChooserY, 0) ) ); 172 | mSettingsPanel->setTransform( Matrix44f::createTranslation( Vec3f(0, mSettingsY, 0) ) ); 173 | 174 | // don't use mPanelOpenY or current height as a constraint here, 175 | // use maximum value because we want things to ease closed 176 | const float maxPanelY = mInterfaceSize.y - getMaxPanelHeight(); 177 | mPanelY = constrain( mPanelY, maxPanelY, mPanelClosedY ); 178 | 179 | Matrix44f transform; 180 | transform.translate( Vec3f( 0, ceil( mPanelY ), 0 ) ); 181 | setTransform( transform ); 182 | } 183 | 184 | void UiLayer::draw() 185 | { 186 | gl::color( Color::white() ); 187 | gl::draw( mButtonsTex, Area( 0, 456, 200, 500 ), mPanelTabRect); 188 | 189 | // draw background for all sub-panels 190 | gl::color( Color::black() ); 191 | gl::drawSolidRect( Rectf(0.0f, 0.0f, mInterfaceSize.x, getMaxPanelHeight()) ); 192 | 193 | // fuck maths, just figure out which is bigger and smaller and stop pretending to know... 194 | const float minY = min(mPanelClosedY, mPanelOpenY); 195 | const float maxY = max(mPanelClosedY, mPanelOpenY); 196 | const float per = ( mPanelY - minY ) / ( maxY - minY ); 197 | // invert (1-per) because higher Y should be darker and lower Y should be lighter 198 | const float dragAlphaPer = min( pow( 1.0f - per, 2.0f ), 1.0f ); 199 | 200 | // top highlight stroke 201 | gl::color( ColorA( BRIGHT_BLUE, 0.1f * dragAlphaPer + 0.1f ) ); 202 | gl::drawLine( Vec2f( 0.0f, 0.0f ), Vec2f( mPanelTabRect.x1 + 22.0f, 0.0f ) ); 203 | 204 | // apply alpha to children 205 | mPlayControls->setOpacity( dragAlphaPer ); 206 | mPlaylistChooser->setOpacity( dragAlphaPer ); 207 | mAlphaChooser->setOpacity( dragAlphaPer ); 208 | mSettingsPanel->setOpacity( dragAlphaPer ); 209 | } 210 | 211 | bool UiLayer::hitTest( Vec2f globalPos ) 212 | { 213 | if (mVisible) { 214 | Vec2f pos = globalToLocal( globalPos ); 215 | return mPanelTabRect.contains(pos) || pos.y > mPanelTabRect.y2; 216 | } 217 | return false; 218 | } 219 | 220 | void UiLayer::setShowAlphaFilter(bool visible) 221 | { 222 | mAlphaChooser->setVisible(visible); 223 | if (visible) { 224 | mPlaylistChooser->setVisible(false); 225 | } 226 | // set dests for sub-panels 227 | mSettingsDestY = mPlayControls->getHeight(); 228 | mChooserDestY = mPlayControls->getHeight(); 229 | if ( isShowingFilter() ) { 230 | mSettingsDestY += max(mAlphaChooser->getHeight(), mPlaylistChooser->getHeight()); 231 | } 232 | mPanelOpenY = mInterfaceSize.y - getPanelHeight(); 233 | } 234 | 235 | bool UiLayer::isShowingAlphaFilter() 236 | { 237 | return mAlphaChooser->isVisible(); 238 | } 239 | 240 | void UiLayer::setShowPlaylistFilter(bool visible) 241 | { 242 | mPlaylistChooser->setVisible(visible); 243 | if (visible) { 244 | mAlphaChooser->setVisible(false); 245 | } 246 | // set dests for sub-panels 247 | mSettingsDestY = mPlayControls->getHeight(); 248 | mChooserDestY = mPlayControls->getHeight(); 249 | if ( isShowingFilter() ) { 250 | mSettingsDestY += max(mAlphaChooser->getHeight(), mPlaylistChooser->getHeight()); 251 | } 252 | mPanelOpenY = mInterfaceSize.y - getPanelHeight(); 253 | } 254 | 255 | bool UiLayer::isShowingPlaylistFilter() 256 | { 257 | return mPlaylistChooser->isVisible(); 258 | } 259 | 260 | bool UiLayer::isShowingFilter() 261 | { 262 | return isShowingPlaylistFilter() || isShowingAlphaFilter(); 263 | } 264 | 265 | float UiLayer::getPanelHeight() 266 | { 267 | float panelHeight = mPlayControls->getHeight(); 268 | if ( isShowingFilter() ) { 269 | panelHeight += max( mPlaylistChooser->getHeight(), mAlphaChooser->getHeight() ); 270 | } 271 | if (mSettingsPanel->isVisible()) { 272 | panelHeight += mSettingsPanel->getHeight(); 273 | } 274 | return panelHeight; 275 | } 276 | 277 | float UiLayer::getMaxPanelHeight() 278 | { 279 | float panelHeight = mPlayControls->getHeight(); 280 | panelHeight += max( mPlaylistChooser->getHeight(), mAlphaChooser->getHeight() ); 281 | panelHeight += mSettingsPanel->getHeight(); 282 | return panelHeight; 283 | } 284 | --------------------------------------------------------------------------------