From 12c5f31562cd2cb56e6430013a5f8279cfa5e757 Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Sun, 8 Dec 2013 09:11:44 +0100 Subject: [PATCH 01/12] Add a buttonMode to grid view to enable it on pointerless devices. --- projects/mtg/include/CarouselDeckView.h | 2 + projects/mtg/include/DeckView.h | 3 +- projects/mtg/include/GridDeckView.h | 5 ++ projects/mtg/src/CarouselDeckView.cpp | 37 +++++++++ projects/mtg/src/DeckView.cpp | 26 ------- projects/mtg/src/GameStateDeckViewer.cpp | 31 ++++---- projects/mtg/src/GridDeckView.cpp | 96 +++++++++++++++++++++++- 7 files changed, 156 insertions(+), 44 deletions(-) diff --git a/projects/mtg/include/CarouselDeckView.h b/projects/mtg/include/CarouselDeckView.h index 9348dcd7b..1c22262b4 100644 --- a/projects/mtg/include/CarouselDeckView.h +++ b/projects/mtg/include/CarouselDeckView.h @@ -27,7 +27,9 @@ public: void Render(); + bool ButtonPressed(Buttons button); MTGCard * Click(int x, int y); + MTGCard * Click(); void changePosition(int offset); void changeFilter(int offset); diff --git a/projects/mtg/include/DeckView.h b/projects/mtg/include/DeckView.h index 268581a31..0534bfaf2 100644 --- a/projects/mtg/include/DeckView.h +++ b/projects/mtg/include/DeckView.h @@ -42,7 +42,8 @@ public: virtual void Render() = 0; virtual MTGCard * Click(int x, int y) = 0; - bool ButtonPressed(Buttons button); + virtual MTGCard * Click() = 0; + virtual bool ButtonPressed(Buttons button) = 0; virtual MTGCard *getActiveCard() = 0; virtual void changePosition(int offset) = 0; virtual void changeFilter(int offset) = 0; diff --git a/projects/mtg/include/GridDeckView.h b/projects/mtg/include/GridDeckView.h index 1e59d4079..981665ac1 100644 --- a/projects/mtg/include/GridDeckView.h +++ b/projects/mtg/include/GridDeckView.h @@ -20,7 +20,9 @@ public: void UpdateCardPosition(CardRep &rep, int index); void Render(); + bool ButtonPressed(Buttons button); MTGCard * Click(int x, int y); + MTGCard * Click(); void changePosition(int offset); void changeFilter(int offset); @@ -33,6 +35,9 @@ private: InOutQuadEasing mScrollEasing; InOutQuadEasing mSlideEasing; int mCurrentSelection; + bool mButtonMode; + + void moveSelection(int offset, bool alignIfOutOfBounds); }; #endif //_GRID_DECK_VIEW_H diff --git a/projects/mtg/src/CarouselDeckView.cpp b/projects/mtg/src/CarouselDeckView.cpp index 0499f7aff..7b03e59b7 100644 --- a/projects/mtg/src/CarouselDeckView.cpp +++ b/projects/mtg/src/CarouselDeckView.cpp @@ -118,6 +118,31 @@ void CarouselDeckView::Render() } } +bool CarouselDeckView::ButtonPressed(Buttons button) +{ + switch(button) + { + case JGE_BTN_LEFT: + changePosition(-1); + last_user_activity = 0; + break; + case JGE_BTN_RIGHT: + changePosition(1); + last_user_activity = 0; + break; + case JGE_BTN_UP: + changeFilter(1); + last_user_activity = 0; + break; + case JGE_BTN_DOWN: + changeFilter(-1); + last_user_activity = 0; + break; + default: + return false; + } + return true; +} MTGCard * CarouselDeckView::Click(int x, int y) { int n = getCardIndexNextTo(x, y); @@ -139,6 +164,18 @@ MTGCard * CarouselDeckView::Click(int x, int y) return NULL; } +MTGCard *CarouselDeckView::Click() +{ + if(mSlideEasing.finished() && mScrollEasing.finished()) + { + return getActiveCard(); + } + else + { + return NULL; + } +} + void CarouselDeckView::changePosition(int offset) { mScrollEasing.start((float)offset, (float)(0.3f*abs(offset))); diff --git a/projects/mtg/src/DeckView.cpp b/projects/mtg/src/DeckView.cpp index 14cb4d5be..8715bfef2 100644 --- a/projects/mtg/src/DeckView.cpp +++ b/projects/mtg/src/DeckView.cpp @@ -41,32 +41,6 @@ void DeckView::Update(float dt) } } -bool DeckView::ButtonPressed(Buttons button) -{ - switch(button) - { - case JGE_BTN_LEFT: - changePosition(-1); - last_user_activity = 0; - break; - case JGE_BTN_RIGHT: - changePosition(1); - last_user_activity = 0; - break; - case JGE_BTN_UP: - changeFilter(1); - last_user_activity = 0; - break; - case JGE_BTN_DOWN: - changeFilter(-1); - last_user_activity = 0; - break; - default: - return false; - } - return true; -} - void DeckView::SetDeck(DeckDataWrapper *toShow) { mCurrentDeck = toShow; diff --git a/projects/mtg/src/GameStateDeckViewer.cpp b/projects/mtg/src/GameStateDeckViewer.cpp index 7e048775b..b660e50a1 100644 --- a/projects/mtg/src/GameStateDeckViewer.cpp +++ b/projects/mtg/src/GameStateDeckViewer.cpp @@ -443,19 +443,21 @@ void GameStateDeckViewer::Update(float dt) int x, y; if (mEngine->GetLeftClickCoordinates(x, y)) { - last_user_activity = 0; mEngine->LeftClickedProcessed(); - if(mView->Click(x, y) == mView->getActiveCard()) + if(mView->Click(x, y) != NULL) { addRemove(mView->getActiveCard()); } } else { - last_user_activity = 0; - addRemove(mView->getActiveCard()); + if(mView->Click() != NULL) + { + addRemove(mView->getActiveCard()); + } } + last_user_activity = 0; mStage = STAGE_WAITING; break; } @@ -468,17 +470,20 @@ void GameStateDeckViewer::Update(float dt) buildEditorMenu(); break; case JGE_BTN_CTRL: - mStage = STAGE_FILTERS; - if (!filterMenu) + if(!mView->ButtonPressed(JGE_BTN_CTRL)) { - filterMenu = NEW WGuiFilters("Filter by...", NULL); - if (source) - SAFE_DELETE(source); - source = NEW WSrcDeckViewer(myDeck, myCollection); - filterMenu->setSrc(source); - if (mView->deck() != myDeck) source->swapSrc(); + mStage = STAGE_FILTERS; + if (!filterMenu) + { + filterMenu = NEW WGuiFilters("Filter by...", NULL); + if (source) + SAFE_DELETE(source); + source = NEW WSrcDeckViewer(myDeck, myCollection); + filterMenu->setSrc(source); + if (mView->deck() != myDeck) source->swapSrc(); + } + filterMenu->Entering(JGE_BTN_NONE); } - filterMenu->Entering(JGE_BTN_NONE); break; case JGE_BTN_PREV: if (last_user_activity < NO_USER_ACTIVITY_HELP_DELAY) diff --git a/projects/mtg/src/GridDeckView.cpp b/projects/mtg/src/GridDeckView.cpp index 1f976eab1..a7a8e32ac 100644 --- a/projects/mtg/src/GridDeckView.cpp +++ b/projects/mtg/src/GridDeckView.cpp @@ -7,7 +7,8 @@ const float GridDeckView::card_scale_big = 0.7f; GridDeckView::GridDeckView() : DeckView(16), mCols(8), mRows(2), mScrollOffset(0), mSlideOffset(0), - mScrollEasing(mScrollOffset), mSlideEasing(mSlideOffset), mCurrentSelection(-1) + mScrollEasing(mScrollOffset), mSlideEasing(mSlideOffset), mCurrentSelection(-1), + mButtonMode(false) { } @@ -23,6 +24,7 @@ void GridDeckView::Reset() mScrollEasing.finish(); mCurrentSelection = 0; + mButtonMode = false; DeckView::Reset(); } @@ -36,14 +38,14 @@ void GridDeckView::UpdateViewState(float dt) if(mScrollOffset <= -1.0f) { SwitchPosition(2); + moveSelection(-2, false); mScrollEasing.translate(1.0f); - mCurrentSelection = (mCurrentSelection >= 6) ? mCurrentSelection - 2 : -1; } else if(mScrollOffset >= 1.0f) { SwitchPosition(-2); + moveSelection(2, false); mScrollEasing.translate(-1.0f); - mCurrentSelection = (mCurrentSelection >= 0 && mCurrentSelection < 10) ? mCurrentSelection + 2 : -1; } dirtyCardPos = true; @@ -138,10 +140,50 @@ void GridDeckView::Render() } } +bool GridDeckView::ButtonPressed(Buttons button) +{ + switch(button) + { + case JGE_BTN_LEFT: + if(mButtonMode) moveSelection(-2, true); + else changePosition(-1); + last_user_activity = 0; + break; + case JGE_BTN_RIGHT: + if(mButtonMode) moveSelection(2, true); + else changePosition(1); + last_user_activity = 0; + break; + case JGE_BTN_UP: + if(mButtonMode) moveSelection(-1, true); + else changeFilter(1); + last_user_activity = 0; + break; + case JGE_BTN_DOWN: + if(mButtonMode) moveSelection(1, true); + else changeFilter(-1); + last_user_activity = 0; + break; + case JGE_BTN_CTRL: + if(mButtonMode) + { + mButtonMode = false; + dirtyCardPos = true; + mCurrentSelection = -1; + } + else return false; + break; + default: + return false; + } + return true; +} + MTGCard * GridDeckView::Click(int x, int y) { int n = getCardIndexNextTo(x, y); last_user_activity = 0; + mButtonMode = false; if(mScrollEasing.finished() && mSlideEasing.finished()) { //clicked and no animations running @@ -167,6 +209,26 @@ MTGCard * GridDeckView::Click(int x, int y) return NULL; } +MTGCard * GridDeckView::Click() +{ + if(mScrollEasing.finished() && mSlideEasing.finished()) + { + MTGCard *active = getActiveCard(); + if(active != NULL) + { + return active; + } + else + { + mButtonMode = true; + dirtyCardPos = true; + mCurrentSelection = 4; + } + } + + return NULL; +} + void GridDeckView::changePosition(int offset) { mScrollEasing.start(-1.0f * offset, scroll_animation_duration * abs(offset)); @@ -188,7 +250,7 @@ void GridDeckView::changeFilter(int offset) MTGCard* GridDeckView::getActiveCard() { - if(mCurrentSelection >= 0 && mCurrentSelection < int(mCards.size())) + if(mCurrentSelection >= 4 && mCurrentSelection < int(mCards.size())-4) { return mCards[mCurrentSelection].card; } @@ -197,3 +259,29 @@ MTGCard* GridDeckView::getActiveCard() return NULL; } } + +void GridDeckView::moveSelection(int offset, bool alignIfOutOfBounds) +{ + mCurrentSelection += offset; + + if(alignIfOutOfBounds) + { + if(mCurrentSelection < 4) + { + changePosition(-1); + } + else if(mCurrentSelection >= 12) + { + changePosition(1); + } + } + else + { + if(mCurrentSelection < 4 || mCurrentSelection >= 12) + { + mCurrentSelection = -1; + } + } + + dirtyCardPos = true; +} From 2b9977a334e933a92f81efe7d458ebd9a8bb8d79 Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Sun, 8 Dec 2013 10:48:15 +0100 Subject: [PATCH 02/12] Rename methods for consistency and add source code doc to DeckView.h --- projects/mtg/include/CarouselDeckView.h | 8 +- projects/mtg/include/DeckView.h | 199 +++++++++++++++++++++-- projects/mtg/include/GridDeckView.h | 6 +- projects/mtg/src/CarouselDeckView.cpp | 42 ++--- projects/mtg/src/DeckView.cpp | 15 +- projects/mtg/src/GameStateDeckViewer.cpp | 4 +- projects/mtg/src/GridDeckView.cpp | 36 ++-- 7 files changed, 243 insertions(+), 67 deletions(-) diff --git a/projects/mtg/include/CarouselDeckView.h b/projects/mtg/include/CarouselDeckView.h index 1c22262b4..7a9b67ee3 100644 --- a/projects/mtg/include/CarouselDeckView.h +++ b/projects/mtg/include/CarouselDeckView.h @@ -18,10 +18,10 @@ public: void Reset(); void UpdateViewState(float dt); - void UpdateCardPosition(CardRep &rep, int index); + void UpdateCardPosition(int index); void renderCard(int index) { - int alpha = (int) (255 * (getCardRep(index).scale + 1.0 - max_scale)); + int alpha = (int) (255 * (mCards[index].scale + 1.0 - max_scale)); DeckView::renderCard(index, alpha); } @@ -31,8 +31,8 @@ public: MTGCard * Click(int x, int y); MTGCard * Click(); - void changePosition(int offset); - void changeFilter(int offset); + void changePositionAnimated(int offset); + void changeFilterAnimated(int offset); MTGCard *getActiveCard(); private: diff --git a/projects/mtg/include/DeckView.h b/projects/mtg/include/DeckView.h index 0534bfaf2..7feec1226 100644 --- a/projects/mtg/include/DeckView.h +++ b/projects/mtg/include/DeckView.h @@ -9,56 +9,233 @@ #include "WResourceManager.h" #include "Pos.h" - +/*! \brief A abstract base class for deck views + * + * The deck editor uses a deck view to present the cards + * e.g. in a circular "Carousel" layout or in a flat grid + * layout. Both layouts inherit this base class to ensure + * a common interface which the deck editor can rely on. + */ class DeckView { protected: + /*! \brief defines the delay until additional card informations get shown + * + * \note I am not entirely sure about that + */ static const float no_user_activity_show_card_delay; -public: + /*! \brief Represents a card for internal use in the deck view + * + * It stores positional information and a pointer to the actual card structure. + */ struct CardRep{ float x; float y; float scale; MTGCard * card; }; - +public: + /*! \brief Defines if the filter needs an update + * + * The owner of the deck that is shown is responsible for updating the filters. + */ bool dirtyFilters; + + /*! \brief Defines if the card positions need an update + * + * If the card positions are dirty, UpdateCardPosition will get called on + * all cards during Update(float dt); + * + * \see Update + * \see UpdateCardPosition + */ bool dirtyCardPos; + /*! \brief Constructs the view and initializes datamembers + * + * It sets the dirty states to true, the currently shown deck to NULL and selects filter 0. + * + * \param numberOfCards the number of cards the view handles (this includes hidden cards for caching) + */ DeckView(int numberOfCards); + + /*! \brief Does nothing but is needed to ensure proper deletion of derived classes. + */ virtual ~DeckView(); + + /*! \brief Resets nearly all datamembers to their initial values + * + * Does not reset mCards. + */ virtual void Reset(); - //advances the view and card representations + /*! \brief Advances the view by dt time units + * + * This method calls UpdateViewState unconditionally and UpdateCardPosition on every card + * if dirtyCardPos is set. It then resets dirtyCardPos. + * + * \param dt the number of time units to advance + * \see UpdateViewState + * \see UpdateCardPosition + */ void Update(float dt); - virtual void SetDeck(DeckDataWrapper *toShow); + + /*! \brief Sets the deck that this view shows + * + * This method replaces the currently shown deck with toShow, sets all dirty states and + * reloads the mtg cards. No ownership changes. + * + * \param toShow the deck to show + * \see reloadIndexes + */ + void SetDeck(DeckDataWrapper *toShow); + + /*! \brief Returns a pointer to the current deck. + */ DeckDataWrapper *deck(); - void SwitchFilter(int delta); - void SwitchPosition(int delta); + + /*! \brief Performs an immediate switch of the filter without animations + * + * This method rotates the currently selected filter by delta and sets dirtyFilters. + * + * \param delta the filter to select relatively to the currently selected filter + * \see dirtyFilters + */ + void changeFilter(int delta); + + /*! \brief Performs an immediate switch of the position without animations + * + * If the i-th card stored in mCards points to the j-th card in the deck, it will point + * to the (j+delta)-th card after this method is called. No dirty states are set. + * + * \param delta the number of cards to advances + * \see mCards + */ + void changePosition(int delta); + + /*! \brief Returns the number of the currently selected filter + * + * \return the currently selected filter + */ int filter(); + + /*! \brief Reloads the mtg card pointers of mCards from the deck + * + * This is called when: We change the position in the deck or the deck structure changes + * (due to filtering or addition or removal of cards). + */ void reloadIndexes(); + + /*! \brief Returns the current position in the deck + */ int getPosition(); + /*! \brief Renders the view + */ virtual void Render() = 0; + + /*! \brief Reacts to selections by a pointer device (e. g. mouse, touch) + * + * If the selection in view internal i. e. a card got selected, there is + * no outside action performed and this method will return NULL. If a action got + * triggered i. e. a selected card was activated, it returns that card + * for further handling by the caller. + * + * \param x the x coordinate of the pointer during the action + * \param y the y coordinate of the pointer during the action + * \returns the card the action corresponds to + */ virtual MTGCard * Click(int x, int y) = 0; + + /*! \brief Reacts to selections by pointerless devices (e. g. buttons) + * + * \see Click(int x, int y) + * \returns the card the actions corresponds to + */ virtual MTGCard * Click() = 0; + + /*! \brief Handles ordinary button presses + * + * \param the pressed JButton + * \returns true if the view reacted to the button and false otherwise + */ virtual bool ButtonPressed(Buttons button) = 0; + + /*! \brief Returns the currently active card + */ virtual MTGCard *getActiveCard() = 0; - virtual void changePosition(int offset) = 0; - virtual void changeFilter(int offset) = 0; + + /*! \brief Changes the position by a given offset + * + * Advances the view by offset cards and animates the change. + * + * \param offset the number of positions to advance + */ + virtual void changePositionAnimated(int offset) = 0; + + /*! \brief Changes the filter by a given offset + * + * Rotates the selected filter by the given offset and animates the change. + */ + virtual void changeFilterAnimated(int offset) = 0; protected: + + /*! \brief The number of time units since an user activity occurred + */ float last_user_activity; + + /*! \brief The currently selected filter + */ int mFilter; + + /*! \brief The currently selected deck + * + * This class does not take ownership of the deck + */ DeckDataWrapper *mCurrentDeck; + + /*! \brief The card positions and pointers + */ vector mCards; - CardRep& getCardRep(unsigned int index); + /*! \brief Renders a card with given alpha value + * + * \param index of the card in mCards to render + * \param alpha the alpha value of the card + * \param asThumbnail renders the thumbnail image of the card if set to true + * + * \see mCards + */ void renderCard(int index, int alpha, bool asThumbnail = false); + + /*! \brief Returns the index in mCards of the card that is nearest to the given point + * + * \note This method uses the euclidian distance to the center of the card + * + * \param x the reference points x coordinate + * \param y the reference points y coordinate + * \returns the index of the nearest card to the reference point and -1 of mCards is empty + */ int getCardIndexNextTo(int x, int y); private: + + /*! \brief Updates the state of the view e. g. view transitions + * + * \param dt the passes time since the last update + */ virtual void UpdateViewState(float dt) = 0; - virtual void UpdateCardPosition(CardRep& rep, int index) = 0; + + /*! \brief Updates the given card reps positional members + * + * This method is called from Update when dirtyCardPos is set + * + * \param index the index in mCards of the card to update + * + * \see Update + * \see mCards + */ + virtual void UpdateCardPosition(int index) = 0; }; #endif // _DECK_VIEW_H_ diff --git a/projects/mtg/include/GridDeckView.h b/projects/mtg/include/GridDeckView.h index 981665ac1..3e85e6288 100644 --- a/projects/mtg/include/GridDeckView.h +++ b/projects/mtg/include/GridDeckView.h @@ -17,15 +17,15 @@ public: void Reset(); void UpdateViewState(float dt); - void UpdateCardPosition(CardRep &rep, int index); + void UpdateCardPosition(int index); void Render(); bool ButtonPressed(Buttons button); MTGCard * Click(int x, int y); MTGCard * Click(); - void changePosition(int offset); - void changeFilter(int offset); + void changePositionAnimated(int offset); + void changeFilterAnimated(int offset); MTGCard *getActiveCard(); private: diff --git a/projects/mtg/src/CarouselDeckView.cpp b/projects/mtg/src/CarouselDeckView.cpp index 7b03e59b7..32b5e43cc 100644 --- a/projects/mtg/src/CarouselDeckView.cpp +++ b/projects/mtg/src/CarouselDeckView.cpp @@ -21,12 +21,12 @@ void CarouselDeckView::UpdateViewState(float dt) if(mScrollOffset <= -1.0f) { - SwitchPosition(-1); + changePosition(-1); mScrollEasing.translate(1.0f); } else if(mScrollOffset >= 1.0f) { - SwitchPosition(1); + changePosition(1); mScrollEasing.translate(-1.0f); } @@ -43,7 +43,7 @@ void CarouselDeckView::UpdateViewState(float dt) if(mSlideOffset < -1.0f) { mSlideEasing.translate(2.0f); - SwitchFilter(1); + changeFilter(1); } } else if(mSlideOffset > mSlideEasing.start_value) @@ -52,7 +52,7 @@ void CarouselDeckView::UpdateViewState(float dt) if(mSlideOffset > 1.0f) { mSlideEasing.translate(-2.0f); - SwitchFilter(-1); + changeFilter(-1); } } @@ -60,8 +60,10 @@ void CarouselDeckView::UpdateViewState(float dt) } } -void CarouselDeckView::UpdateCardPosition(CardRep &rep, int index) +void CarouselDeckView::UpdateCardPosition(int index) { + CardRep &rep = mCards[index]; + float rotation = mScrollOffset + 8 - index; rep.x = x_center + cos((rotation) * M_PI / 12) * (right_border - x_center); @@ -84,13 +86,13 @@ void CarouselDeckView::Render() // in a different order, ie the center card should appear first, then the adjacent ones if (WResourceManager::Instance()->IsThreaded()) { - WResourceManager::Instance()->RetrieveCard(getCardRep(0).card); - WResourceManager::Instance()->RetrieveCard(getCardRep(3).card); - WResourceManager::Instance()->RetrieveCard(getCardRep(4).card); - WResourceManager::Instance()->RetrieveCard(getCardRep(2).card); - WResourceManager::Instance()->RetrieveCard(getCardRep(5).card); - WResourceManager::Instance()->RetrieveCard(getCardRep(1).card); - WResourceManager::Instance()->RetrieveCard(getCardRep(6).card); + WResourceManager::Instance()->RetrieveCard(mCards[0].card); + WResourceManager::Instance()->RetrieveCard(mCards[3].card); + WResourceManager::Instance()->RetrieveCard(mCards[4].card); + WResourceManager::Instance()->RetrieveCard(mCards[2].card); + WResourceManager::Instance()->RetrieveCard(mCards[5].card); + WResourceManager::Instance()->RetrieveCard(mCards[1].card); + WResourceManager::Instance()->RetrieveCard(mCards[6].card); } renderCard(6); @@ -123,19 +125,19 @@ bool CarouselDeckView::ButtonPressed(Buttons button) switch(button) { case JGE_BTN_LEFT: - changePosition(-1); + changePositionAnimated(-1); last_user_activity = 0; break; case JGE_BTN_RIGHT: - changePosition(1); + changePositionAnimated(1); last_user_activity = 0; break; case JGE_BTN_UP: - changeFilter(1); + changeFilterAnimated(1); last_user_activity = 0; break; case JGE_BTN_DOWN: - changeFilter(-1); + changeFilterAnimated(-1); last_user_activity = 0; break; default: @@ -157,7 +159,7 @@ MTGCard * CarouselDeckView::Click(int x, int y) } else { - changePosition(n - 2); + changePositionAnimated(n - 2); } } @@ -176,14 +178,14 @@ MTGCard *CarouselDeckView::Click() } } -void CarouselDeckView::changePosition(int offset) +void CarouselDeckView::changePositionAnimated(int offset) { mScrollEasing.start((float)offset, (float)(0.3f*abs(offset))); last_user_activity = 0; } -void CarouselDeckView::changeFilter(int offset) +void CarouselDeckView::changeFilterAnimated(int offset) { if(offset < 0) { @@ -198,6 +200,6 @@ void CarouselDeckView::changeFilter(int offset) MTGCard *CarouselDeckView::getActiveCard() { - return getCardRep(2).card; + return mCards[2].card; } diff --git a/projects/mtg/src/DeckView.cpp b/projects/mtg/src/DeckView.cpp index 8715bfef2..682b75957 100644 --- a/projects/mtg/src/DeckView.cpp +++ b/projects/mtg/src/DeckView.cpp @@ -35,7 +35,7 @@ void DeckView::Update(float dt) { for(unsigned int i = 0; i < mCards.size(); ++i) { - UpdateCardPosition(mCards[i], i); + UpdateCardPosition(i); } dirtyCardPos = false; } @@ -54,14 +54,14 @@ DeckDataWrapper* DeckView::deck() return mCurrentDeck; } -void DeckView::SwitchFilter(int delta) +void DeckView::changeFilter(int delta) { unsigned int FilterCount = Constants::NB_Colors + 1; mFilter = (FilterCount + mFilter + delta) % FilterCount; dirtyFilters = true; } -void DeckView::SwitchPosition(int delta) +void DeckView::changePosition(int delta) { for(int i = 0; i < delta; ++i) { @@ -92,16 +92,11 @@ void DeckView::reloadIndexes() } } -DeckView::CardRep& DeckView::getCardRep(unsigned int index) -{ - return mCards[index]; -} - void DeckView::renderCard(int index, int alpha, bool asThumbnail) { WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); - const CardRep& cardPosition = getCardRep(index); + const CardRep& cardPosition = mCards[index]; if (!cardPosition.card) return; @@ -187,7 +182,7 @@ int DeckView::getCardIndexNextTo(int x, int y) for(unsigned int i = 0; i < mCards.size(); i++) { - const CardRep& cardPosition = getCardRep(i); + const CardRep& cardPosition = mCards[i]; float dx = (x - cardPosition.x); float dy = (y - cardPosition.y); diff --git a/projects/mtg/src/GameStateDeckViewer.cpp b/projects/mtg/src/GameStateDeckViewer.cpp index b660e50a1..20713d675 100644 --- a/projects/mtg/src/GameStateDeckViewer.cpp +++ b/projects/mtg/src/GameStateDeckViewer.cpp @@ -1532,11 +1532,11 @@ void GameStateDeckViewer::OnScroll(int inXVelocity, int inYVelocity) { //FIXME: this 500 is a bit arbitrary int numCards = (magnitude / 500) % 8; - mView->changePosition(flickRight ? numCards : - numCards); + mView->changePositionAnimated(flickRight ? numCards : - numCards); } } else - mView->changeFilter(flickUp ? 1 : -1); + mView->changeFilterAnimated(flickUp ? 1 : -1); last_user_activity = 0; } diff --git a/projects/mtg/src/GridDeckView.cpp b/projects/mtg/src/GridDeckView.cpp index a7a8e32ac..59c1fbdd8 100644 --- a/projects/mtg/src/GridDeckView.cpp +++ b/projects/mtg/src/GridDeckView.cpp @@ -37,13 +37,13 @@ void GridDeckView::UpdateViewState(float dt) if(mScrollOffset <= -1.0f) { - SwitchPosition(2); + changePosition(2); moveSelection(-2, false); mScrollEasing.translate(1.0f); } else if(mScrollOffset >= 1.0f) { - SwitchPosition(-2); + changePosition(-2); moveSelection(2, false); mScrollEasing.translate(-1.0f); } @@ -58,20 +58,22 @@ void GridDeckView::UpdateViewState(float dt) if(mSlideOffset < -1.0f) { mSlideEasing.translate(2.0f); - SwitchFilter(1); + changeFilter(1); } else if(mSlideOffset > 1.0f) { mSlideEasing.translate(-2.0f); - SwitchFilter(-1); + changeFilter(-1); } dirtyCardPos = true; } } -void GridDeckView::UpdateCardPosition(CardRep &rep, int index) +void GridDeckView::UpdateCardPosition(int index) { + CardRep &rep = mCards[index]; + int col = index / mRows; int row = index % mRows; float colWidth = SCREEN_WIDTH_F / (mCols - 3); @@ -121,7 +123,7 @@ void GridDeckView::Render() { if (WResourceManager::Instance()->IsThreaded()) { - WResourceManager::Instance()->RetrieveCard(getCardRep(i).card, RETRIEVE_THUMB); + WResourceManager::Instance()->RetrieveCard(mCards[i].card, RETRIEVE_THUMB); } renderCard(i, 255, true); } @@ -129,7 +131,7 @@ void GridDeckView::Render() { if (WResourceManager::Instance()->IsThreaded()) { - WResourceManager::Instance()->RetrieveCard(getCardRep(i).card); + WResourceManager::Instance()->RetrieveCard(mCards[i].card); } } } @@ -146,22 +148,22 @@ bool GridDeckView::ButtonPressed(Buttons button) { case JGE_BTN_LEFT: if(mButtonMode) moveSelection(-2, true); - else changePosition(-1); + else changePositionAnimated(-1); last_user_activity = 0; break; case JGE_BTN_RIGHT: if(mButtonMode) moveSelection(2, true); - else changePosition(1); + else changePositionAnimated(1); last_user_activity = 0; break; case JGE_BTN_UP: if(mButtonMode) moveSelection(-1, true); - else changeFilter(1); + else changeFilterAnimated(1); last_user_activity = 0; break; case JGE_BTN_DOWN: if(mButtonMode) moveSelection(1, true); - else changeFilter(-1); + else changeFilterAnimated(-1); last_user_activity = 0; break; case JGE_BTN_CTRL: @@ -193,11 +195,11 @@ MTGCard * GridDeckView::Click(int x, int y) } else if(n < 4) { - changePosition(-1); + changePositionAnimated(-1); } else if(n >= 12) { - changePosition(1); + changePositionAnimated(1); } else { @@ -229,13 +231,13 @@ MTGCard * GridDeckView::Click() return NULL; } -void GridDeckView::changePosition(int offset) +void GridDeckView::changePositionAnimated(int offset) { mScrollEasing.start(-1.0f * offset, scroll_animation_duration * abs(offset)); last_user_activity = 0; } -void GridDeckView::changeFilter(int offset) +void GridDeckView::changeFilterAnimated(int offset) { if(offset < 0) { @@ -268,11 +270,11 @@ void GridDeckView::moveSelection(int offset, bool alignIfOutOfBounds) { if(mCurrentSelection < 4) { - changePosition(-1); + changePositionAnimated(-1); } else if(mCurrentSelection >= 12) { - changePosition(1); + changePositionAnimated(1); } } else From 1cc65ab611a95c8940a8a3fa5435ac885f287b40 Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Sun, 8 Dec 2013 12:03:13 +0100 Subject: [PATCH 03/12] Enable rotating over multiple filters, add src code doc --- projects/mtg/include/CarouselDeckView.h | 1 + projects/mtg/include/GridDeckView.h | 117 ++++++++++++++++++++++- projects/mtg/src/CarouselDeckView.cpp | 15 +-- projects/mtg/src/GameStateDeckViewer.cpp | 9 +- projects/mtg/src/GridDeckView.cpp | 13 +-- 5 files changed, 132 insertions(+), 23 deletions(-) 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; } From 718ceca9191aed3988e2db26436f64e4740331b4 Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Sun, 8 Dec 2013 22:43:03 +0100 Subject: [PATCH 04/12] Do not allow that the selection moves outside in grid view. --- projects/mtg/src/GameStateDeckViewer.cpp | 3 +-- projects/mtg/src/GridDeckView.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/projects/mtg/src/GameStateDeckViewer.cpp b/projects/mtg/src/GameStateDeckViewer.cpp index fe97ee11f..90ced365f 100644 --- a/projects/mtg/src/GameStateDeckViewer.cpp +++ b/projects/mtg/src/GameStateDeckViewer.cpp @@ -407,9 +407,8 @@ void GameStateDeckViewer::Update(float dt) case JGE_BTN_RIGHT: case JGE_BTN_UP: case JGE_BTN_DOWN: - if(last_user_activity > 0.2) + if(mView->ButtonPressed(button)) { - mView->ButtonPressed(button); last_user_activity = 0; mStage = STAGE_WAITING; } diff --git a/projects/mtg/src/GridDeckView.cpp b/projects/mtg/src/GridDeckView.cpp index 922273dd6..36fb9ee4f 100644 --- a/projects/mtg/src/GridDeckView.cpp +++ b/projects/mtg/src/GridDeckView.cpp @@ -147,22 +147,22 @@ bool GridDeckView::ButtonPressed(Buttons button) switch(button) { case JGE_BTN_LEFT: - if(mButtonMode) moveSelection(-2, true); + if(mButtonMode && mScrollEasing.finished()) moveSelection(-2, true); else changePositionAnimated(-1); last_user_activity = 0; break; case JGE_BTN_RIGHT: - if(mButtonMode) moveSelection(2, true); + if(mButtonMode && mScrollEasing.finished()) moveSelection(2, true); else changePositionAnimated(1); last_user_activity = 0; break; case JGE_BTN_UP: - if(mButtonMode) moveSelection(-1, true); + if(mButtonMode && mScrollEasing.finished()) moveSelection(-1, true); else changeFilterAnimated(1); last_user_activity = 0; break; case JGE_BTN_DOWN: - if(mButtonMode) moveSelection(1, true); + if(mButtonMode && mScrollEasing.finished()) moveSelection(1, true); else changeFilterAnimated(-1); last_user_activity = 0; break; From f9dc551942d576fd4191d8e34520ccb840fdebc3 Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Sun, 8 Dec 2013 23:05:06 +0100 Subject: [PATCH 05/12] Fix logic error in grid view --- projects/mtg/src/GridDeckView.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/mtg/src/GridDeckView.cpp b/projects/mtg/src/GridDeckView.cpp index 36fb9ee4f..cfe750448 100644 --- a/projects/mtg/src/GridDeckView.cpp +++ b/projects/mtg/src/GridDeckView.cpp @@ -148,22 +148,22 @@ bool GridDeckView::ButtonPressed(Buttons button) { case JGE_BTN_LEFT: if(mButtonMode && mScrollEasing.finished()) moveSelection(-2, true); - else changePositionAnimated(-1); + else if(!mButtonMode) changePositionAnimated(-1); last_user_activity = 0; break; case JGE_BTN_RIGHT: if(mButtonMode && mScrollEasing.finished()) moveSelection(2, true); - else changePositionAnimated(1); + else if(!mButtonMode) changePositionAnimated(1); last_user_activity = 0; break; case JGE_BTN_UP: if(mButtonMode && mScrollEasing.finished()) moveSelection(-1, true); - else changeFilterAnimated(1); + else if(!mButtonMode) changeFilterAnimated(1); last_user_activity = 0; break; case JGE_BTN_DOWN: if(mButtonMode && mScrollEasing.finished()) moveSelection(1, true); - else changeFilterAnimated(-1); + else if(!mButtonMode) changeFilterAnimated(-1); last_user_activity = 0; break; case JGE_BTN_CTRL: From 7b5f00260b475a39a50aaf86c040e5f6ce8370b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Snoen?= Date: Mon, 9 Dec 2013 16:55:31 +0100 Subject: [PATCH 06/12] Added Avatar Tokens created by Ajani Goldmane. --- projects/mtg/bin/Res/sets/LRW/_cards.dat | 5 +++++ projects/mtg/bin/Res/sets/M10/_cards.dat | 5 +++++ projects/mtg/bin/Res/sets/M11/_cards.dat | 7 ++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/projects/mtg/bin/Res/sets/LRW/_cards.dat b/projects/mtg/bin/Res/sets/LRW/_cards.dat index c1af94093..58a8ff115 100644 --- a/projects/mtg/bin/Res/sets/LRW/_cards.dat +++ b/projects/mtg/bin/Res/sets/LRW/_cards.dat @@ -1513,3 +1513,8 @@ primitive=Zephyr Net id=142357 rarity=C [/card] +[card] +primitive=Avatar Token +id=-140233 +rarity=T +[/card] diff --git a/projects/mtg/bin/Res/sets/M10/_cards.dat b/projects/mtg/bin/Res/sets/M10/_cards.dat index c9c2592fa..d3c646fcd 100644 --- a/projects/mtg/bin/Res/sets/M10/_cards.dat +++ b/projects/mtg/bin/Res/sets/M10/_cards.dat @@ -1248,3 +1248,8 @@ primitive=Zombie Goliath id=190545 rarity=C [/card] +[card] +primitive=Avatar Token +id=-191239 +rarity=T +[/card] diff --git a/projects/mtg/bin/Res/sets/M11/_cards.dat b/projects/mtg/bin/Res/sets/M11/_cards.dat index 6d645a9c3..233184b6b 100644 --- a/projects/mtg/bin/Res/sets/M11/_cards.dat +++ b/projects/mtg/bin/Res/sets/M11/_cards.dat @@ -1257,4 +1257,9 @@ rarity=U primitive=Yavimaya Wurm id=205221 rarity=C -[/card] \ No newline at end of file +[/card] +[card] +primitive=Avatar Token +id=-205957 +rarity=T +[/card] From c62597dce502954a844abd2cf7678cb050fe5a05 Mon Sep 17 00:00:00 2001 From: xawotihs Date: Mon, 9 Dec 2013 21:43:26 +0100 Subject: [PATCH 07/12] Add some debugging to Travis script --- travis-script.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/travis-script.sh b/travis-script.sh index 00f040c4e..bdf8fedef 100755 --- a/travis-script.sh +++ b/travis-script.sh @@ -1,5 +1,10 @@ #!/bin/sh -ex +# let's dump some info to debug a bit +echo PSPDEV = $PSPDEV +echo psp-config = `psp-config --psp-prefix` +echo ls = `ls` + # updating versions with the TRAVIS build numbers cd projects/mtg/ ant update > error.txt From 7528329a5857896ee7f3fe0026036075b66b0d5a Mon Sep 17 00:00:00 2001 From: xawotihs Date: Mon, 9 Dec 2013 21:54:55 +0100 Subject: [PATCH 08/12] Add more debug in travis script --- travis-script.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/travis-script.sh b/travis-script.sh index bdf8fedef..94fd2b762 100755 --- a/travis-script.sh +++ b/travis-script.sh @@ -4,6 +4,8 @@ echo PSPDEV = $PSPDEV echo psp-config = `psp-config --psp-prefix` echo ls = `ls` +echo env = `env` +echo pwd = `pwd` # updating versions with the TRAVIS build numbers cd projects/mtg/ From 5d6557a49f2440dc2f83504660856877f70a710c Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Mon, 9 Dec 2013 16:50:51 +0100 Subject: [PATCH 09/12] Add easing to task list and fix a bug where opening the task list a second time was not possible --- projects/mtg/include/Tasks.h | 13 ++++++++++-- projects/mtg/src/GameStateShop.cpp | 2 +- projects/mtg/src/Tasks.cpp | 32 +++++++++++++++++------------- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/projects/mtg/include/Tasks.h b/projects/mtg/include/Tasks.h index b257752a6..290b8218e 100644 --- a/projects/mtg/include/Tasks.h +++ b/projects/mtg/include/Tasks.h @@ -2,8 +2,15 @@ #define TASK_H #include +#include + +#include "Easing.h" + +using namespace std; class GameObserver; +class JQuad; +class JTexture; // Task type constant @@ -72,8 +79,11 @@ class TaskList { protected: string fileName; + float vPos; - float mElapsed; + InOutQuadEasing vPosInEasing; + InOutQuadEasing vPosOutEasing; + int mState; JQuad * mBg[9]; JTexture * mBgTex; @@ -97,7 +107,6 @@ public: { return mState; } - ; void addTask(string params, bool rand = false); void addTask(Task *task); void addRandomTask(int diff = 100); diff --git a/projects/mtg/src/GameStateShop.cpp b/projects/mtg/src/GameStateShop.cpp index 34ddfa558..7055ed9f5 100644 --- a/projects/mtg/src/GameStateShop.cpp +++ b/projects/mtg/src/GameStateShop.cpp @@ -496,7 +496,7 @@ void GameStateShop::Update(float dt) } break; case STAGE_SHOP_TASKS: - if (menu) + if (menu && !menu->isClosed()) { menu->Update(dt); return; diff --git a/projects/mtg/src/Tasks.cpp b/projects/mtg/src/Tasks.cpp index d1e32a63b..a2399f1e9 100644 --- a/projects/mtg/src/Tasks.cpp +++ b/projects/mtg/src/Tasks.cpp @@ -258,9 +258,10 @@ Task* Task::createFromStr(const string params, bool rand) /*---------------- TaskList -----------------*/ -TaskList::TaskList(string _fileName) +TaskList::TaskList(string _fileName): + fileName(_fileName), vPos(-SCREEN_HEIGHT), vPosInEasing(vPos), vPosOutEasing(vPos) { - fileName = _fileName; + if (fileName == "") { fileName = options.profileFile(PLAYER_TASKS).c_str(); @@ -378,9 +379,10 @@ void TaskList::removeTask(Task *task) void TaskList::Start() { - vPos = -SCREEN_HEIGHT; //Offscreen - mElapsed = 0; mState = TASKS_IN; + vPos = -SCREEN_HEIGHT; //Offscreen + vPosInEasing.start(0.0f, 2.0f); + if (!mBgTex) { mBgTex = WResourceManager::Instance()->RetrieveTexture("taskboard.png", RETRIEVE_LOCK); @@ -410,7 +412,7 @@ void TaskList::Start() void TaskList::End() { mState = TASKS_OUT; - mElapsed = 0; + vPosOutEasing.start(float(-SCREEN_HEIGHT), 2.0f); } void TaskList::passOneDay() @@ -451,21 +453,23 @@ int TaskList::getTaskCount() void TaskList::Update(float dt) { - mElapsed += dt; - - if (mState == TASKS_IN && vPos < 0) + if(!vPosInEasing.finished()) { - vPos = -SCREEN_HEIGHT + (SCREEN_HEIGHT * mElapsed / 0.75f); //Todo: more physical drop-in. - if (vPos >= 0) + vPosInEasing.update(dt); + + if(vPosInEasing.finished()) { - vPos = 0; mState = TaskList::TASKS_ACTIVE; } } - else if (mState == TASKS_OUT && vPos > -SCREEN_HEIGHT) + else if(!vPosOutEasing.finished()) { - vPos = -(SCREEN_HEIGHT * mElapsed / 0.75f); - if (vPos <= -SCREEN_HEIGHT) mState = TASKS_INACTIVE; + vPosOutEasing.update(dt); + + if(vPosOutEasing.finished()) + { + mState = TASKS_INACTIVE; + } } } From 1e610ff6530d091de821d52d11a5f31d7f071a81 Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Mon, 9 Dec 2013 17:21:36 +0100 Subject: [PATCH 10/12] Add InQuadEasing and OutQuadEasing and make tasklists... easing more natural --- projects/mtg/include/Easing.h | 44 +++++++++++++++++++++++++++++++++++ projects/mtg/include/Tasks.h | 4 ++-- projects/mtg/src/Tasks.cpp | 4 ++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/projects/mtg/include/Easing.h b/projects/mtg/include/Easing.h index ccacd4a78..1b5cf35a9 100644 --- a/projects/mtg/include/Easing.h +++ b/projects/mtg/include/Easing.h @@ -167,6 +167,50 @@ public: } }; +/*! \brief This class defines an easing with quadratic acceleration + */ +class InQuadEasing : public Easing +{ +public: + /*! \brief Calls Easing::Easing(val). + * + * \see Easing::Easing(float& val) + */ + InQuadEasing(float& val): Easing(val) {} + + /*! \brief Implements the value calculation. + * + * \see Easing::updateValue() + */ + void updateValue() + { + float time_tmp = time_acc / duration; + value = delta_value * time_tmp * time_tmp + start_value; + } +}; + +/*! \brief This class defines an easing with quadratic decceleration + */ +class OutQuadEasing : public Easing +{ +public: + /*! \brief Calls Easing::Easing(val). + * + * \see Easing::Easing(float& val) + */ + OutQuadEasing(float& val): Easing(val) {} + + /*! \brief Implements the value calculation. + * + * \see Easing::updateValue() + */ + void updateValue() + { + float time_tmp = time_acc / duration; + value = (-delta_value) * time_tmp * (time_tmp - 2.0f) + start_value; + } +}; + /*! \brief This class defines an easing with quadratic acceleration and decceleration. */ class InOutQuadEasing : public Easing diff --git a/projects/mtg/include/Tasks.h b/projects/mtg/include/Tasks.h index 290b8218e..2d96430db 100644 --- a/projects/mtg/include/Tasks.h +++ b/projects/mtg/include/Tasks.h @@ -81,8 +81,8 @@ protected: string fileName; float vPos; - InOutQuadEasing vPosInEasing; - InOutQuadEasing vPosOutEasing; + OutQuadEasing vPosInEasing; + InQuadEasing vPosOutEasing; int mState; JQuad * mBg[9]; diff --git a/projects/mtg/src/Tasks.cpp b/projects/mtg/src/Tasks.cpp index a2399f1e9..48bc9c790 100644 --- a/projects/mtg/src/Tasks.cpp +++ b/projects/mtg/src/Tasks.cpp @@ -381,7 +381,7 @@ void TaskList::Start() { mState = TASKS_IN; vPos = -SCREEN_HEIGHT; //Offscreen - vPosInEasing.start(0.0f, 2.0f); + vPosInEasing.start(0.0f, 1.0f); if (!mBgTex) { @@ -412,7 +412,7 @@ void TaskList::Start() void TaskList::End() { mState = TASKS_OUT; - vPosOutEasing.start(float(-SCREEN_HEIGHT), 2.0f); + vPosOutEasing.start(float(-SCREEN_HEIGHT), 0.9f); } void TaskList::passOneDay() From 4c627f74b6f9d486fd8d368668f8618caca0e36d Mon Sep 17 00:00:00 2001 From: Tobias Loose Date: Mon, 9 Dec 2013 22:17:19 +0100 Subject: [PATCH 11/12] Add easing to GuiPhaseBar, simplify math a bit. --- projects/mtg/include/Easing.h | 2 +- projects/mtg/include/GameStateShop.h | 1 - projects/mtg/include/GuiPhaseBar.h | 16 ++++- projects/mtg/src/GameStateShop.cpp | 6 +- projects/mtg/src/GuiPhaseBar.cpp | 95 +++++++++++----------------- 5 files changed, 53 insertions(+), 67 deletions(-) diff --git a/projects/mtg/include/Easing.h b/projects/mtg/include/Easing.h index 1b5cf35a9..49d574026 100644 --- a/projects/mtg/include/Easing.h +++ b/projects/mtg/include/Easing.h @@ -95,7 +95,7 @@ public: */ void update(float dt) { - if(duration > 0) + if(time_acc < duration) { time_acc += dt; diff --git a/projects/mtg/include/GameStateShop.h b/projects/mtg/include/GameStateShop.h index 1de196b5f..f6765ab74 100644 --- a/projects/mtg/include/GameStateShop.h +++ b/projects/mtg/include/GameStateShop.h @@ -65,7 +65,6 @@ private: JQuadPtr pspIcons[8]; WSrcCards * srcCards; TaskList * taskList; - float mElapsed; WGuiMenu * shopMenu; WGuiFilters * filterMenu; //Filter menu slides in sideways from right, or up from bottom. WGuiCardImage * bigDisplay; diff --git a/projects/mtg/include/GuiPhaseBar.h b/projects/mtg/include/GuiPhaseBar.h index 49dafac6e..78cec2677 100644 --- a/projects/mtg/include/GuiPhaseBar.h +++ b/projects/mtg/include/GuiPhaseBar.h @@ -4,15 +4,25 @@ #include "GuiLayers.h" #include "PhaseRing.h" #include "WEvent.h" +#include "PlayGuiObject.h" + +#include "Easing.h" class GuiPhaseBar: public GuiLayer, public PlayGuiObject { -protected: - Phase* phase; +private: + static const float zoom_big; + static const float zoom_small; + static const float step; + + int displayedPhaseId; float angle; float zoomFactor; - DuelLayers* mpDuelLayers; + OutQuadEasing angleEasing; + InOutQuadEasing zoomFactorEasing; + DuelLayers* mpDuelLayers; + void DrawGlyph(JQuad *inQuad, int phaseId, float x, float y, float scale); public: GuiPhaseBar(DuelLayers* duelLayers); ~GuiPhaseBar(); diff --git a/projects/mtg/src/GameStateShop.cpp b/projects/mtg/src/GameStateShop.cpp index 7055ed9f5..84ca3f6e4 100644 --- a/projects/mtg/src/GameStateShop.cpp +++ b/projects/mtg/src/GameStateShop.cpp @@ -102,7 +102,6 @@ void GameStateShop::Start() bListCards = false; mTouched = false; mStage = STAGE_FADE_IN; - mElapsed = 0; needLoad = true; booster = NULL; srcCards = NEW WSrcUnlockedCards(0); @@ -427,7 +426,7 @@ void GameStateShop::End() { save(); JRenderer::GetInstance()->EnableVSync(false); - mElapsed = 0; + SAFE_DELETE(shopMenu); SAFE_DELETE(bigDisplay); SAFE_DELETE(srcCards); @@ -469,9 +468,6 @@ void GameStateShop::Update(float dt) if (lightAlpha > 50) lightAlpha = 50; - if (mStage != STAGE_FADE_IN) - mElapsed += dt; - JButton btn; switch (mStage) { diff --git a/projects/mtg/src/GuiPhaseBar.cpp b/projects/mtg/src/GuiPhaseBar.cpp index 0accc8a08..8d36cb0f9 100644 --- a/projects/mtg/src/GuiPhaseBar.cpp +++ b/projects/mtg/src/GuiPhaseBar.cpp @@ -24,26 +24,28 @@ }; */ +const float GuiPhaseBar::zoom_big = 1.5 * 1.4; +const float GuiPhaseBar::zoom_small = 1.5; +const float GuiPhaseBar::step = M_PI/6.0f; + namespace { + //width and height of the phase symbol textures const float kWidth = 28; const float kHeight = kWidth; - const unsigned kPhases = 12; + const unsigned kPhases = NB_MTG_PHASES - 2; //there are two phases we do not show +} - const float ICONSCALE = 1.5; - const float CENTER = SCREEN_HEIGHT_F / 2 + 10; - - void DrawGlyph(JQuad* inQuad, int inGlyph, float inY, float, unsigned int inP, float inScale) - { - float xPos = static_cast ((inP + inGlyph * (int) (kWidth + 1)) % (kPhases * (int) (kWidth + 1))); - inQuad->SetTextureRect(xPos, 0, kWidth, kHeight); - JRenderer::GetInstance()->RenderQuad(inQuad, 0, inY, 0.0, inScale, inScale); - } +void GuiPhaseBar::DrawGlyph(JQuad *inQuad, int phaseId, float x, float y, float scale) +{ + inQuad->SetTextureRect(phaseId * (kWidth + 1), 0, kWidth, kHeight); + JRenderer::GetInstance()->RenderQuad(inQuad, x, y - scale * kWidth/2, 0.0f, scale, scale); } GuiPhaseBar::GuiPhaseBar(DuelLayers* duelLayers) : - GuiLayer(duelLayers->getObserver()), PlayGuiObject(0, 0, 106, 0, false), - phase(NULL), angle(0.0f), zoomFactor(ICONSCALE), mpDuelLayers(duelLayers) + GuiLayer(duelLayers->getObserver()), PlayGuiObject(80, 0, 106, 0, false), + displayedPhaseId(0), angle(0.0f), zoomFactor(zoom_small), angleEasing(angle), + zoomFactorEasing(zoomFactor), mpDuelLayers(duelLayers) { if(duelLayers->getObserver()->getResourceManager()) { @@ -57,10 +59,7 @@ GuiPhaseBar::GuiPhaseBar(DuelLayers* duelLayers) : GameApp::systemError = "Error loading phasebar texture : " __FILE__; } - - zoom = ICONSCALE; mpDuelLayers->getCardSelector()->Add(this); - } GuiPhaseBar::~GuiPhaseBar() @@ -69,32 +68,27 @@ GuiPhaseBar::~GuiPhaseBar() void GuiPhaseBar::Update(float dt) { - if (angle > 3 * dt) - angle -= 3 * dt; - else - angle = 0; + angleEasing.update(dt); - if (dt > 0.05f) dt = 0.05f; - if(zoomFactor + 0.05f < zoom) + if(angle <= -step) { - zoomFactor += dt; - } - else if (zoomFactor - 0.05f > zoom) - { - zoomFactor -= dt; + displayedPhaseId = (displayedPhaseId + 1) % kPhases; + angleEasing.translate(step); } + + zoomFactorEasing.update(dt); } void GuiPhaseBar::Entering() { mHasFocus = true; - zoom = 1.4f*ICONSCALE; + zoomFactorEasing.start(zoom_big, 0.3f); } bool GuiPhaseBar::Leaving(JButton) { mHasFocus = false; - zoom = ICONSCALE; + zoomFactorEasing.start(zoom_small, 0.6f); return true; } @@ -102,41 +96,28 @@ void GuiPhaseBar::Render() { JQuadPtr quad = WResourceManager::Instance()->GetQuad("phasebar"); //uncomment to draw a hideous line across hires screens. - // JRenderer::GetInstance()->DrawLine(0, CENTER, SCREEN_WIDTH, CENTER, ARGB(255, 255, 255, 255)); + // JRenderer::GetInstance()->DrawLine(0, CENTER, SCREEN_WIDTH, CENTER, ARGB(255, 255, 255, 255)); - unsigned int p = (phase->id + kPhases - 4) * (int) (kWidth + 1); - float centerYPosition = CENTER + (kWidth / 2) * angle * zoomFactor / (M_PI / 6) - zoomFactor * kWidth / 4; - float yPos = centerYPosition; - float scale = 0; - for (int glyph = 3; glyph < 6; ++glyph) - { - scale = zoomFactor * sinf(angle + glyph * M_PI / 6) / 2; - DrawGlyph(quad.get(), glyph, yPos, angle, p, scale); - yPos += kWidth * scale; - } + const float radius = 25 * zoomFactor; - yPos = centerYPosition; - for (int glyph = 2; glyph > 0; --glyph) + for(int i = 0; i < 6; ++i) { - scale = zoomFactor * sinf(angle + glyph * M_PI / 6) / 2; - yPos -= kWidth * scale; - DrawGlyph(quad.get(), glyph, yPos, angle, p, scale); - } + //the position of the glyphe in the circle + const float circPos = (i - 2) * step + angle; + const float glyphY = this->y + this->mHeight / 2 + sin(circPos) * radius; - if (angle > 0) - { - scale = zoomFactor * sinf(angle) / 2; - yPos -= kWidth * scale; - float xPos = static_cast (p % (kPhases * (int) (kWidth + 1))); - quad->SetTextureRect(xPos, kHeight, kWidth, kHeight); - JRenderer::GetInstance()->RenderQuad(quad.get(), 0, yPos, 0.0, scale, scale); + //the scale is computed so that the glyphes touch each other + //hint: sin(circPos + PI/2) = cos(circPos) + const float glyphScale = zoomFactor * cosf(circPos) * 0.5; + + DrawGlyph(quad.get(), (displayedPhaseId - 3 + kPhases + i) % kPhases, 0, glyphY, glyphScale); } //print phase name WFont * font = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); string currentP = _("your turn"); string interrupt = ""; - if (observer->currentPlayer == mpDuelLayers->getRenderedPlayerOpponent()) + if (observer->currentPlayer == mpDuelLayers->getRenderedPlayerOpponent()) { currentP = _("opponent's turn"); } @@ -147,7 +128,7 @@ void GuiPhaseBar::Render() } if (observer->currentlyActing() != observer->currentPlayer) { - if (observer->currentPlayer == mpDuelLayers->getRenderedPlayer()) + if (observer->currentPlayer == mpDuelLayers->getRenderedPlayer()) { interrupt = _(" - ") + _("opponent plays"); } @@ -159,7 +140,7 @@ void GuiPhaseBar::Render() char buf[200]; //running this string through translate returns gibberish even though we defined the variables in the lang.txt - string phaseNameToTranslate = observer->phaseRing->phaseName(phase->id); + string phaseNameToTranslate = observer->phaseRing->phaseName(displayedPhaseId); phaseNameToTranslate = _(phaseNameToTranslate); sprintf(buf, _("(%s%s) %s").c_str(), currentP.c_str(), interrupt.c_str(),phaseNameToTranslate.c_str()); font->DrawString(buf, SCREEN_WIDTH - 5, 2, JGETEXT_RIGHT); @@ -170,8 +151,8 @@ int GuiPhaseBar::receiveEventMinus(WEvent *e) WEventPhaseChange *event = dynamic_cast (e); if (event) { - angle = M_PI / 6; - phase = event->to; + int phasesToAnimate = (event->to->id - displayedPhaseId + kPhases) % kPhases; + angleEasing.start(float(phasesToAnimate * (- step)), 0.3f * float(sqrt(phasesToAnimate))); } return 1; } From 739a5d9e2bd83f00dc562deaf53fb25ca1b8c131 Mon Sep 17 00:00:00 2001 From: xawotihs Date: Mon, 9 Dec 2013 22:39:25 +0100 Subject: [PATCH 12/12] Removed env traces and change the secure token as it was exposed. --- .travis.yml | 3 ++- travis-script.sh | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d30cd830f..48acd7689 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ install: script: ./travis-script.sh env: global: - secure: YocijVYZa1oDPviFubPIpmBmXyw0gQ7D0YA6tC01wExXvY+8tGUh1HQ5uXn8LotRZ+Ob5HLHDaCzkKWF8+57ILSMeHrnf6tcRyyeO7wjNY9P7WvSZyCjvqnWzsUN9tiMmsEzhTz2MaUgsY6ocB/4nbWZwfQvL7z+s7z41R4J1I4= + secure: "fJgWlCFbde96OSQNGKUmowGX+ERPeqP+n1EOMf1+FJzOU4DdkTLRAlV5+5qnEX9jB/3mWN6iPpmG1qEz/SdDG3KHxJYs4ZU/Lu485O24zZ/+GdYBNsrvhPD9ckPGEMLDa1foEVTDnW0Dlkz3BCFcszjhtXGUJv7v6Pj6LRk1Mg8=" + script: "./travis-script.sh" after_success: ./upload-binaries.sh diff --git a/travis-script.sh b/travis-script.sh index 94fd2b762..db926b1c8 100755 --- a/travis-script.sh +++ b/travis-script.sh @@ -4,7 +4,6 @@ echo PSPDEV = $PSPDEV echo psp-config = `psp-config --psp-prefix` echo ls = `ls` -echo env = `env` echo pwd = `pwd` # updating versions with the TRAVIS build numbers