void LocationApp::setup()
{
    // Define properties
    mHeading = 0.0f;
    timeline().apply( &mRotationAngle, 0.0f, (float)(2 * M_PI), 8.0f ).loop();
    timeline().apply( &mDotRadius, 0.0f, 0.1f, 0.5f ).loop();

    LocationManager::enable();
    LocationManager::getSignalLocationChanged().connect(
        std::bind( &LocationApp::locationChanged, this, std::_1 ) );
#if defined( CINDER_COCOA_TOUCH )
    LocationManager::getSignalHeadingChanged().connect(
        std::bind( &LocationApp::headingChanged, this, std::_1 ) );
#endif

    // Load globe texture,
    setFrameRate( 60.0f );
    mTexture = gl::Texture( loadImage( loadResource( RES_EARTH_JPG ) ) );
    mTexture.setFlipped( true );

    // Set up view
    gl::enable( GL_TEXTURE_2D );
    gl::enableAlphaBlending();

    // Set up light
    mLight = new gl::Light( gl::Light::DIRECTIONAL, 0 );
    mLight->setDirection( Vec3f( 0.0f, 0.1f, 0.3f ).normalized() );
    mLight->setAmbient( ColorAf::gray( 0.843f ) );
    mLight->setDiffuse( ColorAf( 1.0f, 1.0f, 1.0f, 1.0f ) );
    mLight->enable();

    // Build the heading arrow
    float size = 80.0f;
    mArrow.moveTo( Vec2f(         0.0f, -size * 0.5f  ) );
    mArrow.lineTo( Vec2f(  size * 0.5f,  size * 0.5f  ) );
    mArrow.lineTo( Vec2f(         0.0f,  size * 0.25f ) );
    mArrow.lineTo( Vec2f( -size * 0.5f,  size * 0.5f  ) );
    mArrow.close();
}
void PhotoBoothApp::draw()
{
    gl::enableAlphaBlending();
    
    gl::clear();
    gl::color(1, 1, 1, 1);
    glDepthMask( GL_FALSE );

    // Set up the view for landscape mode.
	gl::setMatricesWindow(width * DISPLAY_SCALE, height * DISPLAY_SCALE);
    gl::scale(DISPLAY_SCALE, DISPLAY_SCALE);
    
    // draw the live camera preview
	if( mCameraTexture ) {
        // flip the texture vertically
        mCameraTexture.setFlipped(false);
        
        // draw the texture mirrored.
        gl::draw( mCameraSurface, Rectf(width, 0, 0, height) );
	}

    // draw "idle" stuff (text and images overlayed on the live camera preview)
    if(mCurrentState == STATE_PREVIEW){
        gl::color(1, 1, 1, 0.75f);
        gl::draw(mLightBg, Rectf(0, 0, width, height));
        gl::color(1, 1, 1, 1);
        gl::draw(mIntroTexture, Rectf(0,0,width, height));
        
        gl::draw(mCameraButtonTexture, mCameraButtonPos.value() - Vec2f(0, abs( sin(getElapsedSeconds() * 3) * 30)));

        
        //gl::draw(mCameraButtonTexture, Rectf(mCameraButtonPos.value().x,mCameraButtonPos.value().y, mCameraButtonTexture.getWidth() * 0.5 + mCameraButtonPos.value().x, mCameraButtonTexture.getHeight() * 0.5 + mCameraButtonPos.value().y) );//  mCameraButtonPos.value() );
    }
        
    // Draw the preview image with dark background.
    if(mPreviewTexture){
        
        // draw background image and prompt text.
        if(mDarkBgAlpha > 0){
            gl::color(1, 1, 1, mDarkBgAlpha);
            gl::draw(mDarkBg, Vec2f::zero());
            gl::draw(mConfirmMessage, Vec2f(width/2 - mConfirmMessage.getWidth() / 2, 125 - mConfirmMessage.getHeight() / 2));
        }
        
        float aspect = mPreviewTexture.getAspectRatio();
        
        float imageHeight = height - 500; // margins are keyed off of hard-coded height, this is not very multi-resolution friendly.
        float imageWidth = imageHeight * aspect;
        
        float marginX = (width - imageWidth) / 2;
        float marginY = (height - imageHeight) / 2;
        
        gl::draw(mPreviewTexture, Rectf(marginX, marginY, width - marginX, height - marginY) + mPreviewTexturePos);
        

        // Draw semi-transparent pillar boxes to show how the sqare version of the image will look.
        if(mCurrentState == STATE_ACCEPT) {
            float pillarWidth = (imageWidth - imageHeight) / 2;
            gl::color(0, 0, 0, 0.35f);
            gl::drawSolidRect( Rectf( marginX, height - marginY, pillarWidth + marginX, marginY ) );
            gl::drawSolidRect( Rectf( width - marginX - pillarWidth, height - marginY, width - marginX, marginY ) );
        }
    }
    
    // draw the "flash"
    if(mCurrentState == STATE_ACCEPT){
        gl::color(1, 1, 1, mCameraFlash);
        gl::drawSolidRect( Rectf(0, 0, width, height));
    }
    
    // draw count-down timer
    if(mCurrentState == STATE_COUNT_DOWN){
        
        // draw dark circle background
        Vec2f centerPos = Vec2f(width / 2 - mNumberBg.getWidth() / 2, height / 2 - mNumberBg.getHeight() / 2);
        gl::draw( mNumberBg, centerPos);
        
        // background ring that "fills up" for each second.
        gl::draw(mNumberProgress, Area(0, mNumberProgress.getHeight() * mCountDownFractional, mNumberProgress.getWidth(), mNumberProgress.getHeight()), Rectf(centerPos.x,centerPos.y+mNumberProgress.getHeight() * mCountDownFractional, mNumberBg.getWidth()+centerPos.x, centerPos.y+mNumberBg.getHeight()));
        
        // Draw number.
        gl::enableAdditiveBlending();
        gl::draw( mNumberTextures[mCountDownNumber], centerPos);
    }

    gl::color(1, 1, 1, 1);
    gl::draw(mSaveTexture, mSavePos);
    gl::draw(mDiscardTexture, mDiscardPos);
}