void Camera::Tick(TickParameters &tp)
{
    mTransitionTimer += tp.timespan;
    if(mTransitionTimer >= sTransitionTime)
    {
        mCameraQuaternionStart = mCameraQuaternionEnd;
        mTransitionTimer = 0;
    }

    //Now just interpolate between the two to get the camera orientation
    float transition_factor = smootherstep(0.0f, 1.0f, mTransitionTimer / sTransitionTime);
    mCameraQuaternion = mCameraQuaternionStart.slerp(transition_factor, mCameraQuaternionEnd);

    //Now handle zooming
    mZoomTransitionTimer += tp.timespan;

    float zoom_scalar = 1.0f;
    if(mZoomTransitionTimer >= sTransitionTime)
    {
        mFOVStart = mFOVEnd;
        mCameraOriginStart = mCameraOriginEnd;
        mZoomTransitionTimer = 0;
    }

    zoom_scalar = smootherstep(0.0f, 1.0f, mZoomTransitionTimer / sTransitionTime);

    mCameraOrigin = mCameraOriginStart + (mCameraOriginEnd - mCameraOriginStart) * zoom_scalar;
    mFOV = mFOVStart + (mFOVEnd - mFOVStart) * zoom_scalar;

    //Now calculate camera position by taking a vector and rotating it by the quaternion
    Matrix4f transform = mCameraQuaternion.transform();
    mCameraVector = transform * Vector3f(-WORLD_WIDTH, 0, 0) + mCameraOrigin;
    mCameraUp = transform * Vector3f(0, 1, 0);
}
/* smooth iteration between origin and target on each step */
void morph(float v[])
{
    float ratio=stepIndex/stepCount;
    if (ratio>1) ratio=1;
    if (ratio<0) ratio=0;
    ratio=smootherstep(ratio);
    for (int i=0; i<LEDS; i++)
    {
        float gamma=0.5;
        float o=origin[i];
        float origin=pow(o,gamma);
        float t=target[i];
        float target=pow(t,gamma);
        float lg=origin+(target-origin)*ratio;
        v[i]=(float)pow(lg,1.0/gamma);
    }
}
void ControlTransition::Tick(TickParameters& tp)
{
   std::vector<GuiTransitionControlMessage> tcm = mTransitionControlSubscriber.GetMessages();
   for(std::vector<GuiTransitionControlMessage>::iterator it = tcm.begin(); it != tcm.end(); ++it)
   {
      if(it->TransitionID == mTransitionID)
      {
         if(it->TransitionType == GuiTransition::TransitionIn)
         {
            mTransitionTimer = 0;
            mPendingState = ControlTransitionState::TransIn;
         }
         if(it->TransitionType == GuiTransition::TransitionOut)
         {
            mTransitionTimer = 0;
            mPendingState = ControlTransitionState::TransOut;
         }
      }
   }


   mTransitionTimer += tp.timespan;

   float scalar_alpha = 1.0f;
   float scalar_size = 1.0f;
   switch(mPendingState)
   {
      case ControlTransitionState::TransIn:
         scalar_alpha = smootherstep(0.0f, 1.0f, mTransitionTimer / mTransitionPeriod);
         scalar_size = 0.5f + 0.5f * scalar_alpha;
         break;
      case ControlTransitionState::TransOut:
         scalar_alpha = 1.0f - smootherstep(0.0f, 1.0f, mTransitionTimer / mTransitionPeriod);
         scalar_size = 1.0f + 0.5f * smootherstep(0.0f, 1.0f, mTransitionTimer / mTransitionPeriod);
         scalar_size = clamp(scalar_size, 0.0f, 1.5f);
         break;
      case ControlTransitionState::Hidden:
         scalar_alpha = 0.0f;
         scalar_size = 0.0f;
         break;
      case ControlTransitionState::Visible:
      default:
         scalar_alpha = 1.0f;
         scalar_size = 1.0f;
         break;
   }

   //scalar_alpha = sqrtf(scalar_alpha);

   //Scale size and transparency of rendered parts of the control
   if(mControlArea)
   {
      Vector2f size = mControlArea->GetSize().ToScreen(tp.camera->GetResolution());
      Vector2f top_left = mControlArea->GetPosition().ToScreen(tp.camera->GetResolution(), size);
      Matrix4f scale = Matrix4f::createTranslation(size.x / 2 + top_left.x, size.y / 2 + top_left.y, 0) * 
                       Matrix4f::createScale(scalar_size) * 
                       Matrix4f::createTranslation(-size.x / 2 - top_left.x, -size.y / 2 - top_left.y, 0);

      if(mControlOutline)
      {
         //Scale outline
         mControlOutline->SetTransform(scale);
         mControlOutline->SetAlpha(scalar_alpha);
      }
      
      if(mControlText)
      {
         //Scale text
         mControlText->SetTransform(scale);
         mControlText->SetAlpha(scalar_alpha);
      }

      if(mControlProgress)
      {
         //Scale progress bar
         mControlProgress->SetTransform(scale);
         mControlProgress->SetAlpha(scalar_alpha);
      }
   }
}