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/Animation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/animations/AnimationController.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/LaunchAnimation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/animations/MoveCameraAnimation.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), GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL), mOpacity(255),
mPosition(Eigen::Vector3f::Zero()), mSize(Eigen::Vector2f::Zero()), mTransform(Eigen::Affine3f::Identity()) 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() GuiComponent::~GuiComponent()
{ {
mWindow->removeGui(this); mWindow->removeGui(this);
for(unsigned char i = 0; i < MAX_ANIMATIONS; i++)
{
if(mAnimationMap[i])
delete mAnimationMap[i];
}
if(mParent) if(mParent)
mParent->removeChild(this); mParent->removeChild(this);
@ -33,8 +41,19 @@ bool GuiComponent::input(InputConfig* config, Input input)
void GuiComponent::update(int deltaTime) void GuiComponent::update(int deltaTime)
{ {
if(mAnimationController) for(unsigned char i = 0; i < MAX_ANIMATIONS; i++)
mAnimationController->update(deltaTime); {
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++) 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; GuiComponent* getChild(unsigned int i) const;
// animation will be automatically deleted when it completes or is stopped. // animation will be automatically deleted when it completes or is stopped.
void setAnimation(Animation* animation, std::function<void()> finishedCallback = nullptr, bool reverse = false); void setAnimation(Animation* animation, std::function<void()> finishedCallback = nullptr, bool reverse = false, unsigned char slot = 0);
void stopAnimation(); void stopAnimation(unsigned char slot);
virtual unsigned char getOpacity() const; virtual unsigned char getOpacity() const;
virtual void setOpacity(unsigned char opacity); virtual void setOpacity(unsigned char opacity);
@ -78,9 +78,12 @@ protected:
Eigen::Vector3f mPosition; Eigen::Vector3f mPosition;
Eigen::Vector2f mSize; Eigen::Vector2f mSize;
public:
const static unsigned char MAX_ANIMATIONS = 4;
private: private:
Eigen::Affine3f mTransform; //Don't access this directly! Use getTransform()! Eigen::Affine3f mTransform; //Don't access this directly! Use getTransform()!
std::shared_ptr<AnimationController> mAnimationController; AnimationController* mAnimationMap[MAX_ANIMATIONS];
}; };
#endif #endif

View file

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

View file

@ -12,7 +12,8 @@ public:
AnimationController(Animation* anim, std::function<void()> finishedCallback = nullptr, bool reverse = false); AnimationController(Animation* anim, std::function<void()> finishedCallback = nullptr, bool reverse = false);
virtual ~AnimationController(); virtual ~AnimationController();
void update(int deltaTime); // Returns true if the animation is complete.
bool update(int deltaTime);
private: private:
Animation* mAnimation; 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; bool sleeping = false;
unsigned int timeSinceLastEvent = 0; unsigned int timeSinceLastEvent = 0;
int lastTime = 0; int lastTime = SDL_GetTicks();
bool running = true; bool running = true;
while(running) while(running)
@ -230,8 +230,8 @@ int main(int argc, char* argv[])
deltaTime = 1000; deltaTime = 1000;
window.update(deltaTime); window.update(deltaTime);
Renderer::swapBuffers(); //swap here so we can read the last screen state during updates (see ImageComponent::copyScreen())
window.render(); window.render();
Renderer::swapBuffers();
//sleep if we're past our threshold //sleep if we're past our threshold
//sleeping entails setting a flag to start skipping frames //sleeping entails setting a flag to start skipping frames

View file

@ -7,10 +7,13 @@
#include "GridGameListView.h" #include "GridGameListView.h"
#include "../animations/LaunchAnimation.h" #include "../animations/LaunchAnimation.h"
#include "../animations/MoveCameraAnimation.h" #include "../animations/MoveCameraAnimation.h"
#include "../animations/LambdaAnimation.h"
ViewController::ViewController(Window* window) 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; mState.viewing = START_SCREEN;
} }
@ -95,11 +98,13 @@ void ViewController::launch(FileData* game, Eigen::Vector3f center)
return; return;
} }
game->getSystem()->getTheme()->playSound("gameSelectSound"); game->getSystem()->getTheme()->playSound("gameSelectSound");
Eigen::Affine3f origCamera = mCamera; Eigen::Affine3f origCamera = mCamera;
origCamera.translation() = -mCurrentView->getPosition();
center += 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] setAnimation(new LaunchAnimation(mCamera, mFadeOpacity, center, 1500), [this, origCamera, center, game]
{ {
game->getSystem()->launchGame(mWindow, game); game->getSystem()->launchGame(mWindow, game);