Added a fade in from black for ViewController.

Added LambdaAnimation (which lets you use a lambda for the apply method).
Useful for simple one-off animations.
Added animation slots - only one animation can play per slot.  This way
you can have two animations run at the same time.
This commit is contained in:
Aloshi 2013-12-12 21:17:59 -06:00
parent 67818d5727
commit 7e9b20fac5
8 changed files with 78 additions and 24 deletions

View file

@ -203,6 +203,7 @@ set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/animations/Animation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/animations/AnimationController.h
${CMAKE_CURRENT_SOURCE_DIR}/src/animations/LambdaAnimation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/animations/LaunchAnimation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/animations/MoveCameraAnimation.h

View file

@ -7,12 +7,20 @@
GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL), mOpacity(255),
mPosition(Eigen::Vector3f::Zero()), mSize(Eigen::Vector2f::Zero()), mTransform(Eigen::Affine3f::Identity())
{
for(unsigned char i = 0; i < MAX_ANIMATIONS; i++)
mAnimationMap[i] = NULL;
}
GuiComponent::~GuiComponent()
{
mWindow->removeGui(this);
for(unsigned char i = 0; i < MAX_ANIMATIONS; i++)
{
if(mAnimationMap[i])
delete mAnimationMap[i];
}
if(mParent)
mParent->removeChild(this);
@ -33,8 +41,19 @@ bool GuiComponent::input(InputConfig* config, Input input)
void GuiComponent::update(int deltaTime)
{
if(mAnimationController)
mAnimationController->update(deltaTime);
for(unsigned char i = 0; i < MAX_ANIMATIONS; i++)
{
AnimationController* anim = mAnimationMap[i];
if(anim)
{
bool done = anim->update(deltaTime);
if(done)
{
mAnimationMap[i] = NULL;
delete anim;
}
}
}
for(unsigned int i = 0; i < getChildCount(); i++)
{
@ -186,12 +205,23 @@ void GuiComponent::textInput(const char* text)
}
}
void GuiComponent::setAnimation(Animation* anim, std::function<void()> finishedCallback, bool reverse)
void GuiComponent::setAnimation(Animation* anim, std::function<void()> finishedCallback, bool reverse, unsigned char slot)
{
mAnimationController = std::shared_ptr<AnimationController>(new AnimationController(anim, finishedCallback, reverse));
assert(slot < MAX_ANIMATIONS);
AnimationController* oldAnim = mAnimationMap[slot];
mAnimationMap[slot] = new AnimationController(anim, finishedCallback, reverse);
if(oldAnim)
delete oldAnim;
}
void GuiComponent::stopAnimation()
void GuiComponent::stopAnimation(unsigned char slot)
{
mAnimationController.reset();
assert(slot < MAX_ANIMATIONS);
if(mAnimationMap[slot])
{
delete mAnimationMap[slot];
mAnimationMap[slot] = NULL;
}
}

View file

@ -52,8 +52,8 @@ public:
GuiComponent* getChild(unsigned int i) const;
// animation will be automatically deleted when it completes or is stopped.
void setAnimation(Animation* animation, std::function<void()> finishedCallback = nullptr, bool reverse = false);
void stopAnimation();
void setAnimation(Animation* animation, std::function<void()> finishedCallback = nullptr, bool reverse = false, unsigned char slot = 0);
void stopAnimation(unsigned char slot);
virtual unsigned char getOpacity() const;
virtual void setOpacity(unsigned char opacity);
@ -78,9 +78,12 @@ protected:
Eigen::Vector3f mPosition;
Eigen::Vector2f mSize;
public:
const static unsigned char MAX_ANIMATIONS = 4;
private:
Eigen::Affine3f mTransform; //Don't access this directly! Use getTransform()!
std::shared_ptr<AnimationController> mAnimationController;
AnimationController* mAnimationMap[MAX_ANIMATIONS];
};
#endif

View file

@ -13,7 +13,7 @@ AnimationController::~AnimationController()
delete mAnimation;
}
void AnimationController::update(int deltaTime)
bool AnimationController::update(int deltaTime)
{
mTime += deltaTime;
float t = (float)mTime / mAnimation->getDuration();
@ -26,13 +26,7 @@ void AnimationController::update(int deltaTime)
mAnimation->apply(mReverse ? 1.0f - t : t);
if(t == 1.0f)
{
if(mFinishedCallback)
{
// in case mFinishedCallback causes us to be deleted, use a copy
auto copy = mFinishedCallback;
mFinishedCallback = nullptr;
copy();
}
}
return true;
return false;
}

View file

@ -12,7 +12,8 @@ public:
AnimationController(Animation* anim, std::function<void()> finishedCallback = nullptr, bool reverse = false);
virtual ~AnimationController();
void update(int deltaTime);
// Returns true if the animation is complete.
bool update(int deltaTime);
private:
Animation* mAnimation;

View file

@ -0,0 +1,20 @@
#pragma once
#include "Animation.h"
class LambdaAnimation : public Animation
{
public:
LambdaAnimation(const std::function<void(float t)>& func, int duration) : mFunction(func), mDuration(duration) {}
int getDuration() const override { return mDuration; }
void apply(float t) override
{
mFunction(t);
}
private:
std::function<void(float t)> mFunction;
int mDuration;
};

View file

@ -182,7 +182,7 @@ int main(int argc, char* argv[])
bool sleeping = false;
unsigned int timeSinceLastEvent = 0;
int lastTime = 0;
int lastTime = SDL_GetTicks();
bool running = true;
while(running)
@ -230,8 +230,8 @@ int main(int argc, char* argv[])
deltaTime = 1000;
window.update(deltaTime);
Renderer::swapBuffers(); //swap here so we can read the last screen state during updates (see ImageComponent::copyScreen())
window.render();
Renderer::swapBuffers();
//sleep if we're past our threshold
//sleeping entails setting a flag to start skipping frames

View file

@ -7,10 +7,13 @@
#include "GridGameListView.h"
#include "../animations/LaunchAnimation.h"
#include "../animations/MoveCameraAnimation.h"
#include "../animations/LambdaAnimation.h"
ViewController::ViewController(Window* window)
: GuiComponent(window), mCurrentView(nullptr), mCamera(Eigen::Affine3f::Identity()), mFadeOpacity(0)
: GuiComponent(window), mCurrentView(nullptr), mCamera(Eigen::Affine3f::Identity()), mFadeOpacity(1)
{
// slot 1 so the fade carries over
setAnimation(new LambdaAnimation([&] (float t) { mFadeOpacity = lerp<float>(1.0f, 0.0f, t); }, 900), nullptr, false, 1);
mState.viewing = START_SCREEN;
}
@ -95,11 +98,13 @@ void ViewController::launch(FileData* game, Eigen::Vector3f center)
return;
}
game->getSystem()->getTheme()->playSound("gameSelectSound");
Eigen::Affine3f origCamera = mCamera;
origCamera.translation() = -mCurrentView->getPosition();
center += mCurrentView->getPosition();
stopAnimation(1); // make sure the fade in isn't still playing
setAnimation(new LaunchAnimation(mCamera, mFadeOpacity, center, 1500), [this, origCamera, center, game]
{
game->getSystem()->launchGame(mWindow, game);