diff --git a/projects/mtg/include/CarouselDeckView.h b/projects/mtg/include/CarouselDeckView.h index 7a9b67ee3..7514ed62d 100644 --- a/projects/mtg/include/CarouselDeckView.h +++ b/projects/mtg/include/CarouselDeckView.h @@ -11,6 +11,7 @@ private: static const float x_center; static const float right_border; static const float slide_animation_duration; + static const float scroll_animation_duration; public: CarouselDeckView(); diff --git a/projects/mtg/include/GridDeckView.h b/projects/mtg/include/GridDeckView.h index 3e85e6288..0c164f1f1 100644 --- a/projects/mtg/include/GridDeckView.h +++ b/projects/mtg/include/GridDeckView.h @@ -4,6 +4,15 @@ #include "DeckView.h" #include "Easing.h" +/*! \brief Implements a grid view + * + * This view displays 12 cards in two rows as thumbnails. The currently + * selected card is dislayed bigger than the rest and uses the fullsize + * image. Scrolling the view horizontally and toggeling filters is + * animated and uses quadratic easing. + * + * It also implements a button mode for pointerless devices. + */ class GridDeckView : public DeckView { private: @@ -12,31 +21,133 @@ private: static const float card_scale_small; static const float card_scale_big; public: + /*! \brief Constructs a grid view with no decks set + */ GridDeckView(); + + /*! \brief Does nothing but is needed to ensure proper deletion of derived classes. + */ virtual ~GridDeckView(); + + /*! \brief Resets almost all member variables but mRows and mCols + */ void Reset(); + /*! \brief Advances scrolling and sliding animations + * + * \param dt the time since the last update + * + * \see DeckView::UpdateViewState() + */ void UpdateViewState(float dt); + + /*! \brief Updates the cards position + * + * \see DeckView::UpdateCardPosition() + */ void UpdateCardPosition(int index); + /*! \brief Renders the view + * + * This method prefetches all rendered cards as thumbnails except the + * selected card to reduce cache pressure. + */ void Render(); + + /*! \brief Handles button presses + * + * The mapping is as follows: + * JGE_BTN_LEFT moves the position to the left if not in button mode + * moves the selection otherwise + * JGE_BTN_RIGHT move the position to the right if not in button mode + * moves the selection otherwise + * JGE_BTN_UP select the previous filter if not in button mode + * moves the selection otherwise + * JGE_BTN_DOWN select the next filter if not in button mode + * moves the selection otherwise + * JGE_BTN_CTRL deactivate button mode + * + * \param button the pressed button + * \returns if the view handled the button + */ bool ButtonPressed(Buttons button); + + /*! \brief Handles clicks and triggers scrolling and the selection of cards + * + * This method deactivates the button mode and searches for the nearest + * card to the given position. If this card is in column 0 or 1 it scrolls + * left. If it is in column (mCols-1) or (mCols-2) it scrolls to the right. + * In any other case, it selects the card. + * + * \param x the clicks x coordinate + * \param y the clicks y coordinate + * + * \return selected card c if c was already selected and no animation is running, NULL otherwise + */ MTGCard * Click(int x, int y); + + /*! \brief Handles pointerless clicks (JGE_BTN_OK) + * + * If no card is selected, this method activates button mode and selects a card. + * + * \returns selected card, NULL otherwise + */ MTGCard * Click(); + /*! \brief Scrolls the view horizontally + * + * \param offset the number of columns to scroll + */ void changePositionAnimated(int offset); + + /*! \brief Rotates the selected filter and slides vertically + * + * \param the number of filters to rotate + */ void changeFilterAnimated(int offset); + /*! \brief Returns the currently selected card + * + * \returns card c if c is selected and in column 4 to 6 and NULL otherwise*/ MTGCard *getActiveCard(); private: - int mCols; - int mRows; - float mScrollOffset, mSlideOffset; + /*! \brief The amount of columns (visible and hidden) + */ + const int mCols; + + /*! \brief The amount of rows + */ + const int mRows; + + /*! \brief The current scrolling offset + */ + float mScrollOffset; + + /*! \brief The current sliding offset + */ + float mSlideOffset; + + /*! \brief The easing functor that gets applied while scrolling + */ InOutQuadEasing mScrollEasing; + + /*! \brief The easing functor that gets applied while sliding + */ InOutQuadEasing mSlideEasing; + + /*! \brief The current selected card index + */ int mCurrentSelection; + + /*! \brief Stores if we are in button mode. + */ bool mButtonMode; + /*! \brief Moves the card selection by an offset. + * + * \param offset the offset to move the selection + * \param alignIfOutOfBounds the view will scroll if the selection moves out of bound if set to true + */ void moveSelection(int offset, bool alignIfOutOfBounds); }; diff --git a/projects/mtg/src/CarouselDeckView.cpp b/projects/mtg/src/CarouselDeckView.cpp index 32b5e43cc..7a219dfc0 100644 --- a/projects/mtg/src/CarouselDeckView.cpp +++ b/projects/mtg/src/CarouselDeckView.cpp @@ -4,6 +4,7 @@ const float CarouselDeckView::max_scale = 0.96f; const float CarouselDeckView::x_center = 180; const float CarouselDeckView::right_border = SCREEN_WIDTH + 180; const float CarouselDeckView::slide_animation_duration = 0.6f; +const float CarouselDeckView::scroll_animation_duration = 0.3f; CarouselDeckView::CarouselDeckView() : DeckView(10), mScrollOffset(0), mSlideOffset(0), mScrollEasing(mScrollOffset), mSlideEasing(mSlideOffset) @@ -180,21 +181,15 @@ MTGCard *CarouselDeckView::Click() void CarouselDeckView::changePositionAnimated(int offset) { - mScrollEasing.start((float)offset, (float)(0.3f*abs(offset))); - + if(mScrollEasing.finished()) + mScrollEasing.start((float)offset, (float)(scroll_animation_duration * abs(offset))); last_user_activity = 0; } void CarouselDeckView::changeFilterAnimated(int offset) { - if(offset < 0) - { - mSlideEasing.start(-2.0f, slide_animation_duration); - } - else if(offset > 0) - { - mSlideEasing.start(2.0f, slide_animation_duration); - } + if(mSlideEasing.finished()) + mSlideEasing.start(2.0f * float(offset), float(slide_animation_duration * abs(offset))); last_user_activity = 0; } diff --git a/projects/mtg/src/GameStateDeckViewer.cpp b/projects/mtg/src/GameStateDeckViewer.cpp index 20713d675..fe97ee11f 100644 --- a/projects/mtg/src/GameStateDeckViewer.cpp +++ b/projects/mtg/src/GameStateDeckViewer.cpp @@ -1536,7 +1536,14 @@ void GameStateDeckViewer::OnScroll(int inXVelocity, int inYVelocity) } } else - mView->changeFilterAnimated(flickUp ? 1 : -1); + { + if(abs(inYVelocity) > 300) + { + //FIXME: this 500 is a bit arbitrary + int numFilters = (magnitude / 500); + mView->changeFilterAnimated(flickUp ? numFilters : - numFilters); + } + } last_user_activity = 0; } diff --git a/projects/mtg/src/GridDeckView.cpp b/projects/mtg/src/GridDeckView.cpp index 59c1fbdd8..922273dd6 100644 --- a/projects/mtg/src/GridDeckView.cpp +++ b/projects/mtg/src/GridDeckView.cpp @@ -233,20 +233,15 @@ MTGCard * GridDeckView::Click() void GridDeckView::changePositionAnimated(int offset) { - mScrollEasing.start(-1.0f * offset, scroll_animation_duration * abs(offset)); + if(mScrollEasing.finished()) + mScrollEasing.start(-1.0f * offset, scroll_animation_duration * abs(offset)); last_user_activity = 0; } void GridDeckView::changeFilterAnimated(int offset) { - if(offset < 0) - { - mSlideEasing.start(-2.0f, slide_animation_duration); - } - else if(offset > 0) - { - mSlideEasing.start(2.0f, slide_animation_duration); - } + if(mSlideEasing.finished()) + mSlideEasing.start(2.0f * offset, float(slide_animation_duration * abs(offset))); last_user_activity = 0; }