Make the eased value a reference and add source code doc to Easing.h
This allows to apply multiple easings to the same variable.
This commit is contained in:
@@ -30,11 +30,10 @@ public:
|
||||
void changeFilter(int offset);
|
||||
|
||||
MTGCard *getActiveCard();
|
||||
|
||||
//maintains the current rotation for fluid animations
|
||||
private:
|
||||
InOutQuadEasing mScrollOffset; //[-1,1]. defines the current rotation of the cards
|
||||
InOutQuadEasing mSlide; //[-1,1]. defines, the y-offset of the cards
|
||||
float mScrollOffset, mSlideOffset;
|
||||
InOutQuadEasing mScrollEasing;
|
||||
InOutQuadEasing mSlideEasing;
|
||||
};
|
||||
|
||||
#endif //_CAROUSEL_DECK_VIEW_H_
|
||||
|
||||
@@ -1,33 +1,98 @@
|
||||
#ifndef _EASING_H_
|
||||
#define _EASING_H_
|
||||
|
||||
//see http://www.gizma.com/easing/ for more information
|
||||
/*! \brief A class for eased floats for use in animations
|
||||
*
|
||||
* Animations often defines values a floating point variable
|
||||
* should have at given times and interpolates between them to
|
||||
* calculate the value of that variable at any given intermediate
|
||||
* time step.
|
||||
*
|
||||
* The simplest case would be linear interpolation:
|
||||
* Suppose a float "position" should be a at time = 0 and
|
||||
* b at time = x. If the current time is y, the value of
|
||||
* "position" is then a + (b-a)*y/x.
|
||||
*
|
||||
* This class defines the interface needed to implement different
|
||||
* kind of interpolations with a common interface. See
|
||||
* http://www.gizma.com/easing/ for more information for a few
|
||||
* examples.
|
||||
*/
|
||||
class Easing
|
||||
{
|
||||
public:
|
||||
/*! \brief The value at the start of an animation.
|
||||
*
|
||||
* start_value is undefined if no animation is running.
|
||||
*/
|
||||
float start_value;
|
||||
|
||||
/*! \brief The amount the value should change during the animation.
|
||||
*
|
||||
* delta_value is undefined if no animation is running.
|
||||
*/
|
||||
float delta_value;
|
||||
float value;
|
||||
|
||||
/*! \brief The current value.
|
||||
*
|
||||
* Use this member to read the value or to write the value without
|
||||
* to animate intermediate values and. Make sure that the easing
|
||||
* is not used once value is deleted.
|
||||
*/
|
||||
float& value;
|
||||
|
||||
/*! \brief The duration the animation should take
|
||||
*
|
||||
* It is not relevant which unit is used. This value is undefined
|
||||
* if no animation is running.
|
||||
*/
|
||||
float duration;
|
||||
|
||||
/*! \brief The accumulated time the animation did run until now.
|
||||
*
|
||||
* It is not relevant which unit is used. This values is undefined
|
||||
* if no animation is running.
|
||||
*/
|
||||
float time_acc;
|
||||
|
||||
|
||||
Easing(float val): start_value(val), delta_value(0), value(val), duration(0), time_acc(0)
|
||||
/*! \brief Sets Easing::float to val and sets the animation as not running.
|
||||
*
|
||||
* Make sure that the easing is not used once value is deleted.
|
||||
*
|
||||
* \param val The value to ease
|
||||
*/
|
||||
Easing(float& val): start_value(val), delta_value(0), value(val), duration(0), time_acc(0)
|
||||
{
|
||||
}
|
||||
|
||||
/*! \brief Resets the animation to its initial value
|
||||
*
|
||||
* This method does set the value to the start value and sets the passed time to 0.
|
||||
* If there is no animation animation running, the resulting value is undefined.
|
||||
*/
|
||||
void reset()
|
||||
{
|
||||
value = start_value;
|
||||
time_acc = 0;
|
||||
}
|
||||
|
||||
/*! \brief Finishes the animation immediately
|
||||
*
|
||||
* Sets the value to the animations target value and the passed time to the
|
||||
* animations duration. If there is no animation running, the behaviour is undefined.
|
||||
*/
|
||||
void finish()
|
||||
{
|
||||
value = start_value + delta_value;
|
||||
time_acc = duration;
|
||||
}
|
||||
|
||||
/*! \brief Lets dt time pass
|
||||
*
|
||||
* Advances the animation by dt time units and updates the value accordingly.
|
||||
*
|
||||
* \val dt The amount of time to jump forward
|
||||
*/
|
||||
void update(float dt)
|
||||
{
|
||||
if(duration > 0)
|
||||
@@ -46,8 +111,22 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Calculates the value from all other members.
|
||||
*
|
||||
* This method gets implemented by all specific easing classes.
|
||||
*/
|
||||
virtual void updateValue() = 0;
|
||||
|
||||
/*! \brief Starts the animation.
|
||||
*
|
||||
* Starts the interpolation from the current value (now) to
|
||||
* targetValue (in now + _duration).
|
||||
*
|
||||
* If the animation is currently running, it gets replaced.
|
||||
*
|
||||
* \param targetValue The value to interpolate to
|
||||
* \param _duration The duration the interpolation should take
|
||||
*/
|
||||
void start(float targetValue, float _duration)
|
||||
{
|
||||
start_value = value;
|
||||
@@ -56,23 +135,53 @@ public:
|
||||
duration = _duration;
|
||||
}
|
||||
|
||||
/*! \brief Translates the current value and the target value by delta_value
|
||||
*
|
||||
* This method is mainly used for trickery. Suppose there is one object in the
|
||||
* middle of the screen that should move to the top until it is outside of the
|
||||
* screen and gets replaced by a second one entering the screen from the lower
|
||||
* side once the first one disappeared. This method can be used to simulate this
|
||||
* effect with one animation by translating (i.e. moving) the animation from the
|
||||
* top to the bottom:
|
||||
*
|
||||
* Object1 and object2 are the same object: object1 whose y position is bound to value
|
||||
* To start the transition, use start(SCREEN_HEIGHT, desired time); Once the first
|
||||
* object left the screen (i.e. object.y < 0), change objects appearance to object2
|
||||
* and translate the easing by (SCREEN_HEIGHT).
|
||||
*
|
||||
* \param delta_value The change in start_value and value
|
||||
*/
|
||||
void translate(float delta_value)
|
||||
{
|
||||
start_value += delta_value;
|
||||
value += delta_value;
|
||||
}
|
||||
|
||||
/*! \brief Returns if the passed time exceeds duration.
|
||||
*
|
||||
* If ther is no animation running, it is ensured that this is true.
|
||||
*/
|
||||
bool finished()
|
||||
{
|
||||
return time_acc >= duration;
|
||||
}
|
||||
};
|
||||
|
||||
/*! \brief This class defines an easing with quadratic acceleration and decceleration.
|
||||
*/
|
||||
class InOutQuadEasing : public Easing
|
||||
{
|
||||
public:
|
||||
InOutQuadEasing(float val): Easing(val) {}
|
||||
/*! \brief Calls Easing::Easing(val).
|
||||
*
|
||||
* \see Easing::Easing(float& val)
|
||||
*/
|
||||
InOutQuadEasing(float& val): Easing(val) {}
|
||||
|
||||
/*! \brief Implements the value calculation.
|
||||
*
|
||||
* \see Easing::updateValue()
|
||||
*/
|
||||
void updateValue()
|
||||
{
|
||||
float time_tmp = (time_acc * 2) / duration;
|
||||
|
||||
@@ -27,11 +27,12 @@ public:
|
||||
|
||||
MTGCard *getActiveCard();
|
||||
private:
|
||||
int mCols; //the number of cols. there is a hidden col to the left and right for prefetching
|
||||
int mRows; //the number of rows.
|
||||
InOutQuadEasing mSlide; //[-1,1]. defines the y-offset of the cards
|
||||
InOutQuadEasing mScrollOffset; //[-1,1]. defines the x-offset of the cards
|
||||
int mCurrentSelection; //0 <= mCurrentSelection < mCards.size(). defines the current selected and thus upscaled card
|
||||
int mCols;
|
||||
int mRows;
|
||||
float mScrollOffset, mSlideOffset;
|
||||
InOutQuadEasing mScrollEasing;
|
||||
InOutQuadEasing mSlideEasing;
|
||||
int mCurrentSelection;
|
||||
};
|
||||
|
||||
#endif //_GRID_DECK_VIEW_H
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
const float CarouselDeckView::slide_animation_duration = 0.6f;
|
||||
|
||||
CarouselDeckView::CarouselDeckView() :
|
||||
DeckView(10), mScrollOffset(0), mSlide(0)
|
||||
DeckView(10), mScrollOffset(0), mSlideOffset(0), mScrollEasing(mScrollOffset), mSlideEasing(mSlideOffset)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -12,19 +12,19 @@ CarouselDeckView::~CarouselDeckView()
|
||||
|
||||
void CarouselDeckView::UpdateViewState(float dt)
|
||||
{
|
||||
if(!mScrollOffset.finished())
|
||||
if(!mScrollEasing.finished())
|
||||
{
|
||||
mScrollOffset.update(dt);
|
||||
mScrollEasing.update(dt);
|
||||
|
||||
if(mScrollOffset.value <= -1.0f)
|
||||
if(mScrollOffset <= -1.0f)
|
||||
{
|
||||
mScrollOffset.translate(1.0f);
|
||||
mScrollEasing.translate(1.0f);
|
||||
deck()->prev();
|
||||
reloadIndexes();
|
||||
}
|
||||
else if(mScrollOffset.value >= 1.0f)
|
||||
else if(mScrollOffset >= 1.0f)
|
||||
{
|
||||
mScrollOffset.translate(-1.0f);
|
||||
mScrollEasing.translate(-1.0f);
|
||||
deck()->next();
|
||||
reloadIndexes();
|
||||
}
|
||||
@@ -32,25 +32,25 @@ void CarouselDeckView::UpdateViewState(float dt)
|
||||
dirtyCardPos = true;
|
||||
}
|
||||
|
||||
if(!mSlide.finished())
|
||||
if(!mSlideEasing.finished())
|
||||
{
|
||||
mSlide.update(dt);
|
||||
mSlideEasing.update(dt);
|
||||
|
||||
if(mSlide.value < mSlide.start_value)
|
||||
if(mSlideOffset < mSlideEasing.start_value)
|
||||
{
|
||||
//going downwards
|
||||
if(mSlide.value < -1.0f)
|
||||
if(mSlideOffset < -1.0f)
|
||||
{
|
||||
mSlide.translate(2.0f);
|
||||
mSlideEasing.translate(2.0f);
|
||||
SwitchFilter(1);
|
||||
}
|
||||
}
|
||||
else if(mSlide.value > mSlide.start_value)
|
||||
else if(mSlideOffset > mSlideEasing.start_value)
|
||||
{
|
||||
//upwards
|
||||
if(mSlide.value > 1.0f)
|
||||
if(mSlideOffset > 1.0f)
|
||||
{
|
||||
mSlide.translate(-2.0f);
|
||||
mSlideEasing.translate(-2.0f);
|
||||
SwitchFilter(-1);
|
||||
}
|
||||
}
|
||||
@@ -61,18 +61,19 @@ void CarouselDeckView::UpdateViewState(float dt)
|
||||
|
||||
void CarouselDeckView::UpdateCardPosition(CardRep &rep, int index)
|
||||
{
|
||||
float rotation = mScrollOffset.value + 8 - index;
|
||||
float rotation = mScrollOffset + 8 - index;
|
||||
|
||||
rep.x = x_center + cos((rotation) * M_PI / 12) * (right_border - x_center);
|
||||
rep.scale = max_scale / 1.12f * cos((rep.x - x_center) * 1.5f / (right_border - x_center)) + 0.2f * max_scale * cos(
|
||||
cos((rep.x - x_center) * 0.15f / (right_border - x_center)));
|
||||
rep.y = (SCREEN_HEIGHT_F) / 2.0f + SCREEN_HEIGHT_F * mSlide.value * (rep.scale + 0.2f);
|
||||
rep.y = (SCREEN_HEIGHT_F) / 2.0f + SCREEN_HEIGHT_F * mSlideOffset * (rep.scale + 0.2f);
|
||||
}
|
||||
|
||||
void CarouselDeckView::Reset()
|
||||
{
|
||||
mScrollOffset = 0;
|
||||
mSlide = 0;
|
||||
mSlideEasing.finish();
|
||||
mScrollEasing.finish();
|
||||
|
||||
DeckView::Reset();
|
||||
}
|
||||
|
||||
@@ -96,13 +97,13 @@ void CarouselDeckView::Render()
|
||||
renderCard(4);
|
||||
renderCard(0);
|
||||
|
||||
if (mScrollOffset.value < 0.5 && mScrollOffset.value > -0.5)
|
||||
if (mScrollOffset < 0.5 && mScrollOffset > -0.5)
|
||||
{
|
||||
renderCard(1);
|
||||
renderCard(3);
|
||||
renderCard(2);
|
||||
}
|
||||
else if (mScrollOffset.value < -0.5)
|
||||
else if (mScrollOffset < -0.5)
|
||||
{
|
||||
renderCard(3);
|
||||
renderCard(2);
|
||||
@@ -122,7 +123,7 @@ MTGCard * CarouselDeckView::Click(int x, int y)
|
||||
last_user_activity = 0;
|
||||
|
||||
//clicked active card, and no animation is running
|
||||
if(mSlide.finished() && mScrollOffset.finished())
|
||||
if(mSlideEasing.finished() && mScrollEasing.finished())
|
||||
{
|
||||
if(n == 2)
|
||||
{
|
||||
@@ -140,7 +141,7 @@ MTGCard * CarouselDeckView::Click(int x, int y)
|
||||
|
||||
void CarouselDeckView::changePosition(int offset)
|
||||
{
|
||||
mScrollOffset.start(offset, 0.3f*abs(offset));
|
||||
mScrollEasing.start(offset, 0.3f*abs(offset));
|
||||
|
||||
last_user_activity = 0;
|
||||
}
|
||||
@@ -149,11 +150,11 @@ void CarouselDeckView::changeFilter(int offset)
|
||||
{
|
||||
if(offset < 0)
|
||||
{
|
||||
mSlide.start(-2.0f, slide_animation_duration);
|
||||
mSlideEasing.start(-2.0f, slide_animation_duration);
|
||||
}
|
||||
else if(offset > 0)
|
||||
{
|
||||
mSlide.start(2.0f, slide_animation_duration);
|
||||
mSlideEasing.start(2.0f, slide_animation_duration);
|
||||
}
|
||||
last_user_activity = 0;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ const float GridDeckView::card_scale_small = 0.48f;
|
||||
const float GridDeckView::card_scale_big = 0.7f;
|
||||
|
||||
GridDeckView::GridDeckView()
|
||||
: DeckView(16), mCols(8), mRows(2), mSlide(0), mScrollOffset(0), mCurrentSelection(-1)
|
||||
: DeckView(16), mCols(8), mRows(2), mScrollOffset(0), mSlideOffset(0),
|
||||
mScrollEasing(mScrollOffset), mSlideEasing(mSlideOffset), mCurrentSelection(-1)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -18,31 +19,33 @@ GridDeckView::~GridDeckView()
|
||||
|
||||
void GridDeckView::Reset()
|
||||
{
|
||||
mSlide.finish();
|
||||
mScrollOffset.finish();
|
||||
mSlideEasing.finish();
|
||||
mScrollEasing.finish();
|
||||
|
||||
mCurrentSelection = 0;
|
||||
|
||||
DeckView::Reset();
|
||||
}
|
||||
|
||||
void GridDeckView::UpdateViewState(float dt)
|
||||
{
|
||||
if(!mScrollOffset.finished())
|
||||
if(!mScrollEasing.finished())
|
||||
{
|
||||
mScrollOffset.update(dt);
|
||||
mScrollEasing.update(dt);
|
||||
|
||||
if(mScrollOffset.value <= -1.0f)
|
||||
if(mScrollOffset <= -1.0f)
|
||||
{
|
||||
deck()->next();
|
||||
deck()->next();
|
||||
mScrollOffset.translate(1.0f);
|
||||
mScrollEasing.translate(1.0f);
|
||||
reloadIndexes();
|
||||
mCurrentSelection = (mCurrentSelection >= 6) ? mCurrentSelection - 2 : -1;
|
||||
}
|
||||
else if(mScrollOffset.value >= 1.0f)
|
||||
else if(mScrollOffset >= 1.0f)
|
||||
{
|
||||
deck()->prev();
|
||||
deck()->prev();
|
||||
mScrollOffset.translate(-1.0f);
|
||||
mScrollEasing.translate(-1.0f);
|
||||
reloadIndexes();
|
||||
mCurrentSelection = (mCurrentSelection >= 0 && mCurrentSelection < 10) ? mCurrentSelection + 2 : -1;
|
||||
}
|
||||
@@ -50,27 +53,19 @@ void GridDeckView::UpdateViewState(float dt)
|
||||
dirtyCardPos = true;
|
||||
}
|
||||
|
||||
if(!mSlide.finished())
|
||||
if(!mSlideEasing.finished())
|
||||
{
|
||||
mSlide.update(dt);
|
||||
mSlideEasing.update(dt);
|
||||
|
||||
if(mSlide.value < mSlide.start_value)
|
||||
if(mSlideOffset < -1.0f)
|
||||
{
|
||||
//going downwards
|
||||
if(mSlide.value < -1.0f)
|
||||
{
|
||||
mSlide.translate(2.0f);
|
||||
SwitchFilter(1);
|
||||
}
|
||||
mSlideEasing.translate(2.0f);
|
||||
SwitchFilter(1);
|
||||
}
|
||||
else if(mSlide.value > mSlide.start_value)
|
||||
else if(mSlideOffset > 1.0f)
|
||||
{
|
||||
//upwards
|
||||
if(mSlide.value > 1.0f)
|
||||
{
|
||||
mSlide.translate(-2.0f);
|
||||
SwitchFilter(-1);
|
||||
}
|
||||
mSlideEasing.translate(-2.0f);
|
||||
SwitchFilter(-1);
|
||||
}
|
||||
|
||||
dirtyCardPos = true;
|
||||
@@ -84,8 +79,8 @@ void GridDeckView::UpdateCardPosition(CardRep &rep, int index)
|
||||
float colWidth = SCREEN_WIDTH_F / (mCols - 3);
|
||||
float rowHeight = SCREEN_HEIGHT_F / mRows;
|
||||
|
||||
rep.x = (col + mScrollOffset.value) * colWidth - colWidth;
|
||||
rep.y = row * rowHeight + mSlide.value*SCREEN_HEIGHT + rowHeight/2;
|
||||
rep.x = (col + mScrollOffset) * colWidth - colWidth;
|
||||
rep.y = row * rowHeight + mSlideOffset*SCREEN_HEIGHT + rowHeight/2;
|
||||
|
||||
if(mCurrentSelection == index)
|
||||
{
|
||||
@@ -110,9 +105,9 @@ void GridDeckView::Render()
|
||||
int firstVisibleCard = 2;
|
||||
int lastVisibleCard = mCards.size() - 2;
|
||||
|
||||
if(!mScrollOffset.finished())
|
||||
if(!mScrollEasing.finished())
|
||||
{
|
||||
if(mScrollOffset.delta_value > 0){
|
||||
if(mScrollEasing.delta_value > 0){
|
||||
firstVisibleCard = 0;
|
||||
}
|
||||
else
|
||||
@@ -152,7 +147,7 @@ MTGCard * GridDeckView::Click(int x, int y)
|
||||
int n = getCardIndexNextTo(x, y);
|
||||
last_user_activity = 0;
|
||||
|
||||
if(mScrollOffset.finished() && mSlide.finished())
|
||||
if(mScrollEasing.finished() && mSlideEasing.finished())
|
||||
{ //clicked and no animations running
|
||||
if(n == mCurrentSelection)
|
||||
{
|
||||
@@ -178,7 +173,7 @@ MTGCard * GridDeckView::Click(int x, int y)
|
||||
|
||||
void GridDeckView::changePosition(int offset)
|
||||
{
|
||||
mScrollOffset.start(-1.0f * offset, scroll_animation_duration * abs(offset));
|
||||
mScrollEasing.start(-1.0f * offset, scroll_animation_duration * abs(offset));
|
||||
last_user_activity = 0;
|
||||
}
|
||||
|
||||
@@ -186,11 +181,11 @@ void GridDeckView::changeFilter(int offset)
|
||||
{
|
||||
if(offset < 0)
|
||||
{
|
||||
mSlide.start(-2.0f, slide_animation_duration);
|
||||
mSlideEasing.start(-2.0f, slide_animation_duration);
|
||||
}
|
||||
else if(offset > 0)
|
||||
{
|
||||
mSlide.start(2.0f, slide_animation_duration);
|
||||
mSlideEasing.start(2.0f, slide_animation_duration);
|
||||
}
|
||||
last_user_activity = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user