diff --git a/JGE/Dependencies/lib/libjpeg-static-mt-debug.pdb b/JGE/Dependencies/lib/libjpeg-static-mt-debug.pdb deleted file mode 100644 index 5e7dbba29..000000000 Binary files a/JGE/Dependencies/lib/libjpeg-static-mt-debug.pdb and /dev/null differ diff --git a/JGE/Dependencies/lib/libjpeg-static-mt.pdb b/JGE/Dependencies/lib/libjpeg-static-mt.pdb deleted file mode 100644 index 0c108332a..000000000 Binary files a/JGE/Dependencies/lib/libjpeg-static-mt.pdb and /dev/null differ diff --git a/JGE/include/DebugRoutines.h b/JGE/include/DebugRoutines.h index 1ce188214..43569b162 100644 --- a/JGE/include/DebugRoutines.h +++ b/JGE/include/DebugRoutines.h @@ -61,7 +61,7 @@ std::string ToHex(T* pointer) { \ std::ostringstream stream; \ stream << inString << std::endl; \ - OutputDebugString(stream.str().c_str()); \ + OutputDebugStringA(stream.str().c_str()); \ } #endif // QT_CONFIG #endif // Win32, Linux diff --git a/JGE/src/Qtconsole.cpp b/JGE/src/Qtconsole.cpp index a09f5ba25..447f0d8ba 100644 --- a/JGE/src/Qtconsole.cpp +++ b/JGE/src/Qtconsole.cpp @@ -96,9 +96,8 @@ int main(int argc, char* argv[]) options.reloadProfile(); TestSuite testSuite("test/_tests.txt"); result = testSuite.run(); - int totalTests = testSuite.nbTests + testSuite.nbAITests; delete wagicCore; - DebugTrace("TestSuite done: failed test: " << result << " out of " << totalTests << " total"); + DebugTrace("TestSuite done: failed test: " << result << " out of " << testSuite.nbTests + testSuite.nbAITests << " total"); #ifdef CAPTURE_STDERR OutputCapturer::debugAndClear(); #endif diff --git a/projects/mtg/Android/jni/Android.mk b/projects/mtg/Android/jni/Android.mk index e502bef9c..31f425266 100644 --- a/projects/mtg/Android/jni/Android.mk +++ b/projects/mtg/Android/jni/Android.mk @@ -136,6 +136,9 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.cpp \ $(MTG_PATH)/src/WFont.cpp \ $(MTG_PATH)/src/WGui.cpp \ $(MTG_PATH)/src/WResourceManager.cpp \ + $(MTG_PATH)/src/DeckView.cpp \ + $(MTG_PATH)/src/CarouselDeckView.cpp \ + $(MTG_PATH)/src/GridDeckView.cpp \ $(JGE_PATH)/src/SDLmain.cpp \ $(JGE_PATH)/src/Encoding.cpp \ $(JGE_PATH)/src/JAnimator.cpp \ diff --git a/projects/mtg/Makefile b/projects/mtg/Makefile index a77114104..a5db9bda5 100644 --- a/projects/mtg/Makefile +++ b/projects/mtg/Makefile @@ -27,7 +27,7 @@ OBJS = objs/InteractiveButton.o objs/AbilityParser.o objs/ActionElement.o\ objs/ThisDescriptor.o objs/Token.o objs/Translate.o objs/TranslateKeys.o\ objs/Trash.o objs/utils.o objs/WEvent.o objs/WResourceManager.o\ objs/WCachedResource.o objs/WDataSrc.o objs/WGui.o objs/WFilter.o objs/Tasks.o\ - objs/WFont.o + objs/WFont.o objs/CarouselDeckView.o objs/GridDeckView.o objs/DeckView.o DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS)) RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache) diff --git a/projects/mtg/include/CardGui.h b/projects/mtg/include/CardGui.h index 1ad7d18f1..1957a5505 100644 --- a/projects/mtg/include/CardGui.h +++ b/projects/mtg/include/CardGui.h @@ -33,7 +33,7 @@ protected: /* ** Tries to render the Big version of a card picture, backups to text version in case of failure */ - static void RenderBig(MTGCard * card, const Pos& pos); + static void RenderBig(MTGCard * card, const Pos& pos, bool thumb = false); static void RenderCountersBig(MTGCard * card, const Pos& pos, int drawMode = DrawMode::kNormal); static void AlternateRender(MTGCard * card, const Pos& pos); @@ -55,8 +55,8 @@ public: virtual void Render(); virtual void Update(float dt); - void DrawCard(const Pos& inPosition, int inMode = DrawMode::kNormal); - static void DrawCard(MTGCard* inCard, const Pos& inPosition, int inMode = DrawMode::kNormal); + void DrawCard(const Pos& inPosition, int inMode = DrawMode::kNormal, bool thumb = false); + static void DrawCard(MTGCard* inCard, const Pos& inPosition, int inMode = DrawMode::kNormal, bool thumb = false); static JQuadPtr AlternateThumbQuad(MTGCard * card); virtual ostream& toString(ostream&) const; diff --git a/projects/mtg/include/CarouselDeckView.h b/projects/mtg/include/CarouselDeckView.h new file mode 100644 index 000000000..9348dcd7b --- /dev/null +++ b/projects/mtg/include/CarouselDeckView.h @@ -0,0 +1,42 @@ +#ifndef _CAROUSEL_DECK_VIEW_H_ +#define _CAROUSEL_DECK_VIEW_H_ + +#include "DeckView.h" +#include "Easing.h" + +class CarouselDeckView : public DeckView +{ +private: + static const float max_scale; + static const float x_center; + static const float right_border; + static const float slide_animation_duration; + +public: + CarouselDeckView(); + virtual ~CarouselDeckView(); + void Reset(); + + void UpdateViewState(float dt); + void UpdateCardPosition(CardRep &rep, int index); + void renderCard(int index) + { + int alpha = (int) (255 * (getCardRep(index).scale + 1.0 - max_scale)); + DeckView::renderCard(index, alpha); + } + + void Render(); + + MTGCard * Click(int x, int y); + + void changePosition(int offset); + void changeFilter(int offset); + + MTGCard *getActiveCard(); +private: + float mScrollOffset, mSlideOffset; + InOutQuadEasing mScrollEasing; + InOutQuadEasing mSlideEasing; +}; + +#endif //_CAROUSEL_DECK_VIEW_H_ diff --git a/projects/mtg/include/DeckView.h b/projects/mtg/include/DeckView.h new file mode 100644 index 000000000..268581a31 --- /dev/null +++ b/projects/mtg/include/DeckView.h @@ -0,0 +1,63 @@ +#ifndef _DECK_VIEW_H_ +#define _DECK_VIEW_H_ + +#include + +#include "MTGCard.h" +#include "DeckDataWrapper.h" +#include "WFont.h" +#include "WResourceManager.h" +#include "Pos.h" + + +class DeckView +{ +protected: + static const float no_user_activity_show_card_delay; + +public: + struct CardRep{ + float x; + float y; + float scale; + MTGCard * card; + }; + + bool dirtyFilters; + bool dirtyCardPos; + + DeckView(int numberOfCards); + virtual ~DeckView(); + virtual void Reset(); + + //advances the view and card representations + void Update(float dt); + virtual void SetDeck(DeckDataWrapper *toShow); + DeckDataWrapper *deck(); + void SwitchFilter(int delta); + void SwitchPosition(int delta); + int filter(); + void reloadIndexes(); + int getPosition(); + + virtual void Render() = 0; + virtual MTGCard * Click(int x, int y) = 0; + bool ButtonPressed(Buttons button); + virtual MTGCard *getActiveCard() = 0; + virtual void changePosition(int offset) = 0; + virtual void changeFilter(int offset) = 0; +protected: + float last_user_activity; + int mFilter; + DeckDataWrapper *mCurrentDeck; + vector mCards; + + CardRep& getCardRep(unsigned int index); + void renderCard(int index, int alpha, bool asThumbnail = false); + int getCardIndexNextTo(int x, int y); +private: + virtual void UpdateViewState(float dt) = 0; + virtual void UpdateCardPosition(CardRep& rep, int index) = 0; +}; + +#endif // _DECK_VIEW_H_ diff --git a/projects/mtg/include/Easing.h b/projects/mtg/include/Easing.h new file mode 100644 index 000000000..ccacd4a78 --- /dev/null +++ b/projects/mtg/include/Easing.h @@ -0,0 +1,201 @@ +#ifndef _EASING_H_ +#define _EASING_H_ + +/*! \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; + + /*! \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; + + /*! \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) + { + time_acc += dt; + + if(time_acc > duration) + { + time_acc = duration; + value = start_value + delta_value; + } + else + { + updateValue(); + } + } + } + + /*! \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; + delta_value = targetValue - start_value; + time_acc = 0; + 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: + /*! \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; + if (time_tmp < 1) + { + value = (float)(delta_value * 0.5 * time_tmp * time_tmp + start_value); + } + else + { + time_tmp -= 1; + value = (float)(- delta_value * 0.5 * (time_tmp * (time_tmp - 2) - 1) + start_value); + } + } +}; + + +#endif //_EASING_H_ diff --git a/projects/mtg/include/GameStateDeckViewer.h b/projects/mtg/include/GameStateDeckViewer.h index 426bb7226..50da6b4b3 100644 --- a/projects/mtg/include/GameStateDeckViewer.h +++ b/projects/mtg/include/GameStateDeckViewer.h @@ -19,22 +19,7 @@ #include "WGui.h" #include "InteractiveButton.h" -#define NO_USER_ACTIVITY_HELP_DELAY 10 -#define NO_USER_ACTIVITY_SHOWCARD_DELAY 0.1 - -enum -{ - STAGE_TRANSITION_RIGHT = 0, - STAGE_TRANSITION_LEFT = 1, - STAGE_WAITING = 2, - STAGE_TRANSITION_UP = 3, - STAGE_TRANSITION_DOWN = 4, - STAGE_ONSCREEN_MENU = 5, - STAGE_WELCOME = 6, - STAGE_MENU = 7, - STAGE_FILTERS = 8, - STAGE_TRANSITION_SELECTED = 9 -}; +class DeckView; // TODO: need a better name for MENU_FIRST_MENU, this is reused for the 1st submenu of // available options in the duel menu @@ -44,7 +29,7 @@ enum MENU_DECK_SELECTION = 10, MENU_DECK_BUILDER = 11, MENU_FIRST_DUEL_SUBMENU = 102, - MENU_LANGUAGE_SELECTION = 103, + MENU_LANGUAGE_SELECTION = 103 }; // enums for menu options @@ -64,79 +49,69 @@ enum DECK_VIEWER_MENU_ITEMS MENU_ITEM_NO = 21, MENU_ITEM_FILTER_BY = 22, MENUITEM_MORE_INFO = kInfoMenuID - }; -#define ALL_COLORS -1 - -#define ROTATE_LEFT 1; -#define ROTATE_RIGHT 0; - -#define HIGH_SPEED 15.0 -#define MED_SPEED 5.0f -#define LOW_SPEED 1.5 - -#define MAX_SAVED_FILTERS Constants::NB_Colors + 1 -#define CARDS_DISPLAYED 10 - class GameStateDeckViewer: public GameState, public JGuiListener { private: + enum DeckViewerStages + { + STAGE_WAITING = 0, + STAGE_ONSCREEN_MENU, + STAGE_WELCOME, + STAGE_MENU, + STAGE_FILTERS + }; + vector mIcons; JQuadPtr pspIcons[8]; JTexture * pspIconsTexture; float last_user_activity; float onScreenTransition; - float mRotation; - float mSlide; - int mAlpha; - int mStage; - int useFilter; + DeckViewerStages mStage; JMusic * bgMusic; - int lastPos; - int lastTotal; - int mSelected; - InteractiveButton *toggleDeckButton, *sellCardButton, *statsPrevButton, *filterButton; + InteractiveButton *toggleDeckButton, *sellCardButton, *statsPrevButton, *filterButton, *toggleViewButton; WGuiFilters * filterMenu; WSrcDeckViewer * source; DeckEditorMenu * welcome_menu; SimpleMenu * subMenu; - DeckEditorMenu * menu; + DeckEditorMenu * deckMenu; PriceList* pricelist; PlayerData * playerdata; - int price; - DeckDataWrapper * displayed_deck; DeckDataWrapper * myDeck; DeckDataWrapper * myCollection; - MTGCard * cardIndex[CARDS_DISPLAYED]; - StatsWrapper *stw; + StatsWrapper * mStatsWrapper; int hudAlpha; string newDeckname; bool isAIDeckSave; bool mSwitching; + + enum AvailableView{ + CAROUSEL_VIEW, + GRID_VIEW + }; + DeckView* mView; + AvailableView mCurrentView; + void saveDeck(); //Saves the deck and additional necessary information void saveAsAIDeck(string deckName); // saves deck as an AI Deck - int getCurrentPos(); void sellCard(); void setButtonState(bool state); bool userPressedButton(); void RenderButtons(); - - pair cardsCoordinates[CARDS_DISPLAYED]; - + void setupView(AvailableView view, DeckDataWrapper *deck); + void toggleView(); public: GameStateDeckViewer(GameApp* parent); virtual ~GameStateDeckViewer(); void updateDecks(); - void rotateCards(int direction); - void loadIndexes(); void updateFilters(); void rebuildFilters(); - void switchDisplay(); + void toggleCollection(); void Start(); virtual void End(); void addRemove(MTGCard * card); @@ -145,11 +120,8 @@ public: void renderSlideBar(); void renderDeckBackground(); void renderOnScreenMenu(); - virtual void renderCard(int id, float rotation); - virtual void renderCard(int id); virtual void Render(); int loadDeck(int deckid); - void LoadDeckStatistics(int deckId); void OnScroll(int inXVelocity, int inYVelocity); diff --git a/projects/mtg/include/GridDeckView.h b/projects/mtg/include/GridDeckView.h new file mode 100644 index 000000000..1e59d4079 --- /dev/null +++ b/projects/mtg/include/GridDeckView.h @@ -0,0 +1,38 @@ +#ifndef _GRID_DECK_VIEW_H +#define _GRID_DECK_VIEW_H + +#include "DeckView.h" +#include "Easing.h" + +class GridDeckView : public DeckView +{ +private: + static const float scroll_animation_duration; + static const float slide_animation_duration; + static const float card_scale_small; + static const float card_scale_big; +public: + GridDeckView(); + virtual ~GridDeckView(); + void Reset(); + + void UpdateViewState(float dt); + void UpdateCardPosition(CardRep &rep, int index); + + void Render(); + MTGCard * Click(int x, int y); + + void changePosition(int offset); + void changeFilter(int offset); + + MTGCard *getActiveCard(); +private: + int mCols; + int mRows; + float mScrollOffset, mSlideOffset; + InOutQuadEasing mScrollEasing; + InOutQuadEasing mSlideEasing; + int mCurrentSelection; +}; + +#endif //_GRID_DECK_VIEW_H diff --git a/projects/mtg/include/GuiMana.h b/projects/mtg/include/GuiMana.h index d18655bc9..de9f68641 100644 --- a/projects/mtg/include/GuiMana.h +++ b/projects/mtg/include/GuiMana.h @@ -6,8 +6,9 @@ #include #include "JGE.h" #include "MTGDefinitions.h" -#include "GameApp.h" +#include "Pos.h" #include "GuiLayers.h" +#include "WResource_Fwd.h" class ManaIcon : public Pos { diff --git a/projects/mtg/include/InteractiveButton.h b/projects/mtg/include/InteractiveButton.h index 3a7f52aca..d15e768bc 100644 --- a/projects/mtg/include/InteractiveButton.h +++ b/projects/mtg/include/InteractiveButton.h @@ -28,6 +28,7 @@ const int kNextStatsButtonId = 10005; const int kPrevStatsButtonId = 10006; const int kCycleCardsButtonId = 10007; const int kShowCardListButtonId = 10008; +const int kSwitchViewButton = 10009; class InteractiveButton: public SimpleButton { diff --git a/projects/mtg/include/MTGDeck.h b/projects/mtg/include/MTGDeck.h index c17e83189..fcba1b192 100644 --- a/projects/mtg/include/MTGDeck.h +++ b/projects/mtg/include/MTGDeck.h @@ -4,7 +4,6 @@ #define MTG_ERROR -1 #include "MTGDefinitions.h" -#include "GameApp.h" #include "WResourceManager.h" #include #include diff --git a/projects/mtg/include/ObjectAnalytics.h b/projects/mtg/include/ObjectAnalytics.h index db610a54c..43306f801 100644 --- a/projects/mtg/include/ObjectAnalytics.h +++ b/projects/mtg/include/ObjectAnalytics.h @@ -1,6 +1,8 @@ #ifndef OBJECTANALYTICS_H #define OBJECTANALYTICS_H +#include + #ifdef _DEBUG #define TRACK_OBJECT_USAGE #endif diff --git a/projects/mtg/include/OptionItem.h b/projects/mtg/include/OptionItem.h index 7664e82d8..998d9cb67 100644 --- a/projects/mtg/include/OptionItem.h +++ b/projects/mtg/include/OptionItem.h @@ -7,7 +7,6 @@ #include #include #include -#include "GameApp.h" #include "GameStateOptions.h" #include "WFilter.h" #include "WDataSrc.h" diff --git a/projects/mtg/include/PriceList.h b/projects/mtg/include/PriceList.h index 7af69b5e4..f08281e88 100644 --- a/projects/mtg/include/PriceList.h +++ b/projects/mtg/include/PriceList.h @@ -20,16 +20,18 @@ public: ~PriceList(); int save(); int getSellPrice(int cardid); + int getSellPrice(MTGCard* card); int getPurchasePrice(int cardid); + int getPrice(MTGCard *card); int getPrice(int cardId); int setPrice(int cardId, int price); + int setPrice(MTGCard *card, int price); int getOtherPrice(int amt); static float difficultyScalar(float price, int cardid = 0); static void updateKey() { randomKey = rand(); } - ; }; #endif diff --git a/projects/mtg/include/Tasks.h b/projects/mtg/include/Tasks.h index 2eb8b7340..b257752a6 100644 --- a/projects/mtg/include/Tasks.h +++ b/projects/mtg/include/Tasks.h @@ -3,6 +3,8 @@ #include +class GameObserver; + // Task type constant #define TASK_BASIC 'B' diff --git a/projects/mtg/include/WFilter.h b/projects/mtg/include/WFilter.h index 2ec34538a..16d30c59d 100644 --- a/projects/mtg/include/WFilter.h +++ b/projects/mtg/include/WFilter.h @@ -1,3 +1,5 @@ +#include "MTGDeck.h" + #ifndef _WFILTER_H_ #define _WFILTER_H_ /** diff --git a/projects/mtg/include/WGui.h b/projects/mtg/include/WGui.h index 60dab9a7b..008d29658 100644 --- a/projects/mtg/include/WGui.h +++ b/projects/mtg/include/WGui.h @@ -8,6 +8,7 @@ class hgeDistortionMesh; class GameStateOptions; +class SimpleMenu; /** @defgroup WGui Basic Gui diff --git a/projects/mtg/include/utils.h b/projects/mtg/include/utils.h index 3a3461b40..25a4c392d 100644 --- a/projects/mtg/include/utils.h +++ b/projects/mtg/include/utils.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "DebugRoutines.h" diff --git a/projects/mtg/src/CardGui.cpp b/projects/mtg/src/CardGui.cpp index 0c414ae94..859a6d936 100644 --- a/projects/mtg/src/CardGui.cpp +++ b/projects/mtg/src/CardGui.cpp @@ -17,6 +17,7 @@ #include "Counters.h" #include "ModRules.h" #include "CardDescriptor.h" +#include "GameApp.h" const float CardGui::Width = 28.0; const float CardGui::Height = 40.0; @@ -110,17 +111,17 @@ void CardGui::Update(float dt) PlayGuiObject::Update(dt); } -void CardGui::DrawCard(const Pos& inPosition, int inMode) +void CardGui::DrawCard(const Pos& inPosition, int inMode, bool thumb) { - DrawCard(card, inPosition, inMode); + DrawCard(card, inPosition, inMode, thumb); } -void CardGui::DrawCard(MTGCard* inCard, const Pos& inPosition, int inMode) +void CardGui::DrawCard(MTGCard* inCard, const Pos& inPosition, int inMode, bool thumb) { switch (inMode) { case DrawMode::kNormal: - RenderBig(inCard, inPosition); + RenderBig(inCard, inPosition, thumb); break; case DrawMode::kText: AlternateRender(inCard, inPosition); @@ -957,7 +958,7 @@ void CardGui::TinyCropRender(MTGCard * card, const Pos& pos, JQuad * quad) } //Renders a big card on screen. Defaults to the "alternate" rendering if no image is found -void CardGui::RenderBig(MTGCard* card, const Pos& pos) +void CardGui::RenderBig(MTGCard* card, const Pos& pos, bool thumb) { JRenderer * renderer = JRenderer::GetInstance(); //GameObserver * game = GameObserver::GetInstance(); @@ -966,7 +967,8 @@ void CardGui::RenderBig(MTGCard* card, const Pos& pos) //i want this but ai targets cards so quickly that it can crash the game. float x = pos.actX; - JQuadPtr quad = WResourceManager::Instance()->RetrieveCard(card); + JQuadPtr quad = thumb ? WResourceManager::Instance()->RetrieveCard(card, RETRIEVE_THUMB) + : WResourceManager::Instance()->RetrieveCard(card); MTGCardInstance * kcard = dynamic_cast(card); if(kcard && !kcard->isToken && kcard->name != kcard->model->data->name) { diff --git a/projects/mtg/src/CardPrimitive.cpp b/projects/mtg/src/CardPrimitive.cpp index b399bfb07..462457492 100644 --- a/projects/mtg/src/CardPrimitive.cpp +++ b/projects/mtg/src/CardPrimitive.cpp @@ -6,6 +6,7 @@ #include "MTGDeck.h" #include "Subtypes.h" #include "Translate.h" +#include "GameApp.h" using std::string; diff --git a/projects/mtg/src/CarouselDeckView.cpp b/projects/mtg/src/CarouselDeckView.cpp new file mode 100644 index 000000000..0499f7aff --- /dev/null +++ b/projects/mtg/src/CarouselDeckView.cpp @@ -0,0 +1,166 @@ +#include "CarouselDeckView.h" + +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; + +CarouselDeckView::CarouselDeckView() : + DeckView(10), mScrollOffset(0), mSlideOffset(0), mScrollEasing(mScrollOffset), mSlideEasing(mSlideOffset) +{ +} + +CarouselDeckView::~CarouselDeckView() +{} + +void CarouselDeckView::UpdateViewState(float dt) +{ + if(!mScrollEasing.finished()) + { + mScrollEasing.update(dt); + + if(mScrollOffset <= -1.0f) + { + SwitchPosition(-1); + mScrollEasing.translate(1.0f); + } + else if(mScrollOffset >= 1.0f) + { + SwitchPosition(1); + mScrollEasing.translate(-1.0f); + } + + dirtyCardPos = true; + } + + if(!mSlideEasing.finished()) + { + mSlideEasing.update(dt); + + if(mSlideOffset < mSlideEasing.start_value) + { + //going downwards + if(mSlideOffset < -1.0f) + { + mSlideEasing.translate(2.0f); + SwitchFilter(1); + } + } + else if(mSlideOffset > mSlideEasing.start_value) + { + //upwards + if(mSlideOffset > 1.0f) + { + mSlideEasing.translate(-2.0f); + SwitchFilter(-1); + } + } + + dirtyCardPos = true; + } +} + +void CarouselDeckView::UpdateCardPosition(CardRep &rep, int 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 * mSlideOffset * (rep.scale + 0.2f); +} + +void CarouselDeckView::Reset() +{ + mSlideEasing.finish(); + mScrollEasing.finish(); + + DeckView::Reset(); +} + +void CarouselDeckView::Render() +{ + // even though we want to draw the cards in a particular z order for layering, we want to prefetch them + // 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); + } + + renderCard(6); + renderCard(5); + renderCard(4); + renderCard(0); + + if (mScrollOffset < 0.5 && mScrollOffset > -0.5) + { + renderCard(1); + renderCard(3); + renderCard(2); + } + else if (mScrollOffset < -0.5) + { + renderCard(3); + renderCard(2); + renderCard(1); + } + else + { + renderCard(1); + renderCard(2); + renderCard(3); + } +} + +MTGCard * CarouselDeckView::Click(int x, int y) +{ + int n = getCardIndexNextTo(x, y); + last_user_activity = 0; + + //clicked active card, and no animation is running + if(mSlideEasing.finished() && mScrollEasing.finished()) + { + if(n == 2) + { + return getActiveCard(); + } + else + { + changePosition(n - 2); + } + } + + return NULL; +} + +void CarouselDeckView::changePosition(int offset) +{ + mScrollEasing.start((float)offset, (float)(0.3f*abs(offset))); + + last_user_activity = 0; +} + +void CarouselDeckView::changeFilter(int offset) +{ + if(offset < 0) + { + mSlideEasing.start(-2.0f, slide_animation_duration); + } + else if(offset > 0) + { + mSlideEasing.start(2.0f, slide_animation_duration); + } + last_user_activity = 0; +} + +MTGCard *CarouselDeckView::getActiveCard() +{ + return getCardRep(2).card; +} + diff --git a/projects/mtg/src/DeckView.cpp b/projects/mtg/src/DeckView.cpp new file mode 100644 index 000000000..912e68757 --- /dev/null +++ b/projects/mtg/src/DeckView.cpp @@ -0,0 +1,242 @@ +#include "DeckView.h" + +#include "GameOptions.h" +#include "CardGui.h" + +const float DeckView::no_user_activity_show_card_delay = 0.1f; + +DeckView::DeckView(int numberOfCards) + : dirtyFilters(true), dirtyCardPos(true), last_user_activity(0.0f), mFilter(0), mCurrentDeck(NULL) +{ + mCards.resize(numberOfCards); +} + +DeckView::~DeckView() +{ + +} + +void DeckView::Reset() +{ + dirtyFilters = true; + dirtyCardPos = true; + last_user_activity = 0; + mFilter = 0; + mCurrentDeck = NULL; +} + +void DeckView::Update(float dt) +{ + last_user_activity += dt; + + UpdateViewState(dt); + + if(dirtyCardPos) + { + for(unsigned int i = 0; i < mCards.size(); ++i) + { + UpdateCardPosition(mCards[i], i); + } + dirtyCardPos = false; + } +} + +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; + reloadIndexes(); +} + +DeckDataWrapper* DeckView::deck() +{ + return mCurrentDeck; +} + +void DeckView::SwitchFilter(int delta) +{ + unsigned int FilterCount = Constants::NB_Colors + 1; + mFilter = (FilterCount + mFilter + delta) % FilterCount; + dirtyFilters = true; +} + +void DeckView::SwitchPosition(int delta) +{ + for(int i = 0; i < delta; ++i) + { + mCurrentDeck->next(); + } + + for(int i = 0; i > delta; --i) + { + mCurrentDeck->prev(); + } + + reloadIndexes(); +} + +int DeckView::filter() +{ + return mFilter; +} + +void DeckView::reloadIndexes() +{ + if(mCurrentDeck != NULL) + { + for (unsigned int i = 0; i < mCards.size(); i++) + { + mCards[i].card = deck()->getCard(i); + } + } +} + +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); + + if (!cardPosition.card) return; + + if (!WResourceManager::Instance()->IsThreaded()) + { + JQuadPtr backQuad = WResourceManager::Instance()->GetQuad(kGenericCardID); + JQuadPtr quad; + + int cacheError = CACHE_ERROR_NONE; + + if (!options[Options::DISABLECARDS].number) + { + quad = WResourceManager::Instance()->RetrieveCard(cardPosition.card, RETRIEVE_EXISTING); + cacheError = WResourceManager::Instance()->RetrieveError(); + if (!quad.get() && cacheError != CACHE_ERROR_404) + { + if (last_user_activity > (abs(2 - index) + 1) * no_user_activity_show_card_delay) + quad = WResourceManager::Instance()->RetrieveCard(cardPosition.card); + else + { + quad = backQuad; + } + } + } + + if (quad.get()) + { + if (quad == backQuad) + { + quad->SetColor(ARGB(255,255,255,255)); + float _scale = cardPosition.scale * (285 / quad->mHeight); + JRenderer::GetInstance()->RenderQuad(quad.get(), cardPosition.x, cardPosition.y, 0.0f, _scale, _scale); + } + else + { + Pos pos = Pos(cardPosition.x, cardPosition.y, cardPosition.scale * 285 / 250, 0.0, 255); + CardGui::DrawCard(cardPosition.card, pos, asThumbnail); + } + } + else + { + Pos pos = Pos(cardPosition.x, cardPosition.y, cardPosition.scale * 285 / 250, 0.0, 255); + CardGui::DrawCard(cardPosition.card, pos, DrawMode::kText, asThumbnail); + } + } + else + { + int mode = !options[Options::DISABLECARDS].number ? DrawMode::kNormal : DrawMode::kText; + + Pos pos = Pos(cardPosition.x, cardPosition.y, cardPosition.scale * 285 / 250, 0.0, 255); + CardGui::DrawCard(cardPosition.card, pos, mode, asThumbnail); + } + + int quadAlpha = alpha; + if (!deck()->count(cardPosition.card)) quadAlpha /= 2; + quadAlpha = 255 - quadAlpha; + if (quadAlpha > 0) + { + JRenderer::GetInstance()->FillRect(cardPosition.x - cardPosition.scale * 100.0f, cardPosition.y - cardPosition.scale * 142.5f, cardPosition.scale * 200.0f, cardPosition.scale * 285.0f, + ARGB(quadAlpha,0,0,0)); + } + if (last_user_activity < 3) + { + int fontAlpha = alpha; + float qtY = cardPosition.y - 135 * cardPosition.scale; + float qtX = cardPosition.x + 40 * cardPosition.scale; + char buffer[4096]; + sprintf(buffer, "x%i", deck()->count(cardPosition.card)); + WFont * font = mFont; + font->SetColor(ARGB(fontAlpha/2,0,0,0)); + JRenderer::GetInstance()->FillRect(qtX, qtY, font->GetStringWidth(buffer) + 6, 16, ARGB(fontAlpha/2,0,0,0)); + font->DrawString(buffer, qtX + 4, qtY + 4); + font->SetColor(ARGB(fontAlpha,255,255,255)); + font->DrawString(buffer, qtX + 2, qtY + 2); + font->SetColor(ARGB(255,255,255,255)); + } +} + +int DeckView::getCardIndexNextTo(int x, int y) +{ + int bestCardIndex = -1; + float bestDistance = 0; + + for(unsigned int i = 0; i < mCards.size(); i++) + { + const CardRep& cardPosition = getCardRep(i); + + float dx = (x - cardPosition.x); + float dy = (y - cardPosition.y); + float dist = dx*dx + dy*dy; + + if(dist < bestDistance || bestCardIndex == -1) + { + bestDistance = dist; + bestCardIndex = i; + } + } + + return bestCardIndex; +} + +int DeckView::getPosition() +{ + if(!mCurrentDeck) + { + return 0; + } + + int total = mCurrentDeck->Size(); + int currentPos = (mCurrentDeck->getOffset() + 3) % total; + + while (currentPos <= 0) currentPos += total; + return currentPos; +} diff --git a/projects/mtg/src/GameStateDeckViewer.cpp b/projects/mtg/src/GameStateDeckViewer.cpp index 24e51f910..ec19d9b7e 100644 --- a/projects/mtg/src/GameStateDeckViewer.cpp +++ b/projects/mtg/src/GameStateDeckViewer.cpp @@ -21,13 +21,17 @@ #include "SimpleMenu.h" #include "utils.h" #include "AIPlayer.h" +#include "GameApp.h" +#include "CarouselDeckView.h" +#include "GridDeckView.h" + +#define NO_USER_ACTIVITY_HELP_DELAY 10 GameStateDeckViewer::GameStateDeckViewer(GameApp* parent) : - GameState(parent, "deckeditor") + GameState(parent, "deckeditor"), mView(NULL), mCurrentView(CAROUSEL_VIEW) { bgMusic = NULL; - useFilter = 0; isAIDeckSave = false; mSwitching = false; welcome_menu = NULL; @@ -37,16 +41,15 @@ GameStateDeckViewer::GameStateDeckViewer(GameApp* parent) : source = NULL; hudAlpha = 0; subMenu = NULL; - mRotation = 0; - mSlide = 0; - mAlpha = 255; - menu = NULL; - stw = NULL; + deckMenu = NULL; + mStatsWrapper = NULL; statsPrevButton = NEW InteractiveButton(NULL, kPrevStatsButtonId, Fonts::MAIN_FONT, "Stats", SCREEN_WIDTH_F - 50, SCREEN_HEIGHT_F - 20, JGE_BTN_PREV); toggleDeckButton = NEW InteractiveButton(NULL, kToggleDeckActionId, Fonts::MAIN_FONT, "View Deck", 10, SCREEN_HEIGHT_F - 20, JGE_BTN_PRI); sellCardButton = NEW InteractiveButton(NULL, kSellCardActionId, Fonts::MAIN_FONT, "Sell Card", (SCREEN_WIDTH_F/ 2) - 100, SCREEN_HEIGHT_F - 20, JGE_BTN_SEC); filterButton = NEW InteractiveButton(NULL, kFilterButtonId, Fonts::MAIN_FONT, "filter", (SCREEN_WIDTH_F - 110), SCREEN_HEIGHT_F - 20, JGE_BTN_CTRL); + //TODO: Check if that button is available: + toggleViewButton = NEW InteractiveButton(NULL, kSwitchViewButton, Fonts::MAIN_FONT, "Grid", (SCREEN_WIDTH_F/ 2) + 50, SCREEN_HEIGHT_F - 20, JGE_BTN_MAX); } GameStateDeckViewer::~GameStateDeckViewer() @@ -56,6 +59,8 @@ GameStateDeckViewer::~GameStateDeckViewer() SAFE_DELETE(sellCardButton); SAFE_DELETE(statsPrevButton); SAFE_DELETE(filterButton); + SAFE_DELETE(toggleViewButton); + SAFE_DELETE(mView); if (myDeck) { @@ -70,24 +75,6 @@ GameStateDeckViewer::~GameStateDeckViewer() SAFE_DELETE(filterMenu); } -void GameStateDeckViewer::rotateCards(int direction) -{ - int left = direction; - if (left) - displayed_deck->next(); - else - displayed_deck->prev(); - loadIndexes(); - - int total = displayed_deck->Size(); - if (total) - { - lastPos = getCurrentPos(); - lastTotal = total; - } - -} - void GameStateDeckViewer::rebuildFilters() { if (!filterMenu) filterMenu = NEW WGuiFilters("Filter by...", NULL); @@ -95,108 +82,73 @@ void GameStateDeckViewer::rebuildFilters() SAFE_DELETE(source); source = NEW WSrcDeckViewer(myDeck, myCollection); filterMenu->setSrc(source); - if (displayed_deck != myDeck) source->swapSrc(); + if (mView->deck() != myDeck) source->swapSrc(); filterMenu->Finish(true); - // no stats need updating if there isn't a deck to update - if (stw && myDeck) - stw->updateStats( myDeck );; + // no stats need updating if there isn't a deck to update + if (mStatsWrapper && myDeck) + mStatsWrapper->updateStats( myDeck );; } void GameStateDeckViewer::updateFilters() { - if (!displayed_deck) return; + if (!mView->deck() || !filterMenu) return; - filterMenu->recolorFilter(useFilter - 1); + filterMenu->recolorFilter(mView->filter() - 1); filterMenu->Finish(true); - int totalAfter = displayed_deck->Size(); - if (totalAfter && lastTotal) - { - - //This part is a hack. I don't understand why in some cases "displayed_deck's" currentPos is not 0 at this stage - { - while (int currentPos = displayed_deck->getOffset()) - { - if (currentPos > 0) - displayed_deck->prev(); - else - displayed_deck->next(); - } - } - - int pos = (totalAfter * lastPos) / lastTotal; - for (int i = 0; i < pos - 3; ++i) - { // "-3" because card "0" is displayed at position 3 initially - displayed_deck->next(); - } - } - stw->updateStats( myDeck );; + mStatsWrapper->updateStats( myDeck );; return; } -void GameStateDeckViewer::loadIndexes() +void GameStateDeckViewer::toggleCollection() { - for (int i = 0; i < 7; i++) + if (mView->deck() == myCollection) { - cardIndex[i] = displayed_deck->getCard(i); - } -} - -void GameStateDeckViewer::switchDisplay() -{ - if (displayed_deck == myCollection) - { - displayed_deck = myDeck; toggleDeckButton->setText("View Collection"); + mView->SetDeck(myDeck); } else { toggleDeckButton->setText("View Deck"); - displayed_deck = myCollection; + mView->SetDeck(myCollection); } source->swapSrc(); updateFilters(); - loadIndexes(); } +//after renaming and on the first start. +//reloadWelcomeMenu void GameStateDeckViewer::updateDecks() { SAFE_DELETE(welcome_menu); welcome_menu = NEW DeckEditorMenu(MENU_DECK_SELECTION, this, Fonts::OPTION_FONT, "Choose Deck To Edit"); - DeckManager * deckManager = DeckManager::GetInstance(); vector playerDeckList = fillDeckMenu(welcome_menu, options.profileFile()); newDeckname = ""; welcome_menu->Add(MENU_ITEM_NEW_DECK, "--NEW--"); - if (options[Options::CHEATMODE].number && (!myCollection || myCollection->getCount(WSrcDeck::UNFILTERED_MIN_COPIES) < 4)) welcome_menu->Add( - MENU_ITEM_CHEAT_MODE, "--UNLOCK CARDS--"); + if (options[Options::CHEATMODE].number && (!myCollection || myCollection->getCount(WSrcDeck::UNFILTERED_MIN_COPIES) < 4)) + { + welcome_menu->Add(MENU_ITEM_CHEAT_MODE, "--UNLOCK CARDS--"); + } welcome_menu->Add(MENU_ITEM_CANCEL, "Cancel"); // update the deckmanager with the latest information - deckManager->updateMetaDataList(&playerDeckList, false); - // is this necessary to ensure no memory leaks? - playerDeckList.clear(); + DeckManager::GetInstance()->updateMetaDataList(&playerDeckList, false); } void GameStateDeckViewer::buildEditorMenu() { - ostringstream deckSummaryInformation; - deckSummaryInformation << _("All changes are final.").c_str() << endl; + SAFE_DELETE(deckMenu); - if (menu) - SAFE_DELETE( menu ); - //Build menu. - JRenderer::GetInstance()->FillRoundRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 100, ARGB(0, 0, 0, 0) ); - menu = NEW DeckEditorMenu(MENU_DECK_BUILDER, this, Fonts::OPTION_FONT, "Deck Editor", myDeck, stw); - - menu->Add(MENU_ITEM_FILTER_BY, _("Filter By...").c_str(), _("Narrow down the list of cards. ").c_str()); - menu->Add(MENU_ITEM_SWITCH_DECKS_NO_SAVE, _("Switch Decks").c_str(), _("Do not make any changes. View another deck.").c_str()); - menu->Add(MENU_ITEM_SAVE_RENAME, _("Rename Deck").c_str(), _("Change the name of the deck").c_str()); - menu->Add(MENU_ITEM_SAVE_RETURN_MAIN_MENU, _("Save & Quit Editor").c_str(), _("Save changes. Return to the main menu").c_str()); - menu->Add(MENU_ITEM_SAVE_AS_AI_DECK, _("Save As AI Deck").c_str(), deckSummaryInformation.str()); - menu->Add(MENU_ITEM_MAIN_MENU, _("Quit Editor").c_str(), _("Do not make any changes to deck. Return to the main menu.").c_str()); - menu->Add(MENU_ITEM_EDITOR_CANCEL, _("Cancel").c_str(), _("Close menu.").c_str()); + deckMenu = NEW DeckEditorMenu(MENU_DECK_BUILDER, this, Fonts::OPTION_FONT, "Deck Editor", myDeck, mStatsWrapper); + deckMenu->Add(MENU_ITEM_FILTER_BY, _("Filter By..."), _("Narrow down the list of cards. ")); + deckMenu->Add(MENU_ITEM_SWITCH_DECKS_NO_SAVE, _("Switch Decks"), _("Do not make any changes. View another deck.")); + deckMenu->Add(MENU_ITEM_SAVE_RENAME, _("Rename Deck"), _("Change the name of the deck")); + deckMenu->Add(MENU_ITEM_SAVE_RETURN_MAIN_MENU, _("Save & Quit Editor"), _("Save changes. Return to the main menu")); + deckMenu->Add(MENU_ITEM_SAVE_AS_AI_DECK, _("Save As AI Deck"), _("All changes are final.")); + deckMenu->Add(MENU_ITEM_MAIN_MENU, _("Quit Editor"), _("Do not make any changes to deck. Return to the main menu.")); + deckMenu->Add(MENU_ITEM_EDITOR_CANCEL, _("Cancel"), _("Close menu.")); } void GameStateDeckViewer::Start() @@ -206,20 +158,15 @@ void GameStateDeckViewer::Start() subMenu = NULL; myDeck = NULL; mStage = STAGE_WELCOME; - mRotation = 0; - mSlide = 0; - mAlpha = 255; + last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; onScreenTransition = 0; - useFilter = 0; - lastPos = 0; - lastTotal = 0; pricelist = NEW PriceList("settings/prices.dat", MTGCollection()); playerdata = NEW PlayerData(MTGCollection()); myCollection = NEW DeckDataWrapper(playerdata->collection); myCollection->Sort(WSrcCards::SORT_ALPHA); - displayed_deck = myCollection; + setupView(mCurrentView, myCollection); //Icons mIcons = manaIcons; @@ -248,7 +195,6 @@ void GameStateDeckViewer::Start() GameApp::playMusic("Track1.mp3"); - loadIndexes(); mEngine->ResetInput(); JRenderer::GetInstance()->EnableVSync(true); } @@ -258,7 +204,7 @@ void GameStateDeckViewer::End() JRenderer::GetInstance()->EnableVSync(false); SAFE_DELETE(welcome_menu); - SAFE_DELETE(menu); + SAFE_DELETE(deckMenu); SAFE_DELETE(subMenu); WResourceManager::Instance()->Release(pspIconsTexture); @@ -280,9 +226,9 @@ void GameStateDeckViewer::End() void GameStateDeckViewer::addRemove(MTGCard * card) { if (!card) return; - if (displayed_deck->Remove(card, 1, (displayed_deck == myDeck))) + if (mView->deck()->Remove(card, 1, (mView->deck() == myDeck))) { - if (displayed_deck == myCollection) + if (mView->deck() == myCollection) { myDeck->Add(card); myDeck->Sort(WSrcCards::SORT_ALPHA); @@ -294,8 +240,8 @@ void GameStateDeckViewer::addRemove(MTGCard * card) } myCollection->validate(); myDeck->validate(); - stw->needUpdate = true; - loadIndexes(); + mStatsWrapper->needUpdate = true; + mView->reloadIndexes(); } void GameStateDeckViewer::saveDeck() @@ -340,10 +286,10 @@ void GameStateDeckViewer::sellCard() SAFE_DELETE(subMenu); char buffer[4096]; { - MTGCard * card = cardIndex[2]; - if (card && displayed_deck->count(card)) + MTGCard * card = mView->getActiveCard(); + if (card && mView->deck()->count(card)) { - price = pricelist->getSellPrice(card->getMTGId()); + int price = pricelist->getSellPrice(card); sprintf(buffer, "%s : %i %s", _(card->data->getName()).c_str(), price, _("credits").c_str()); const float menuXOffset = SCREEN_WIDTH_F - 300; const float menuYOffset = SCREEN_HEIGHT_F / 2; @@ -352,18 +298,18 @@ void GameStateDeckViewer::sellCard() subMenu->Add(MENU_ITEM_NO, "No", "", true); } } - stw->needUpdate = true; + mStatsWrapper->needUpdate = true; } bool GameStateDeckViewer::userPressedButton() { - return ( - (toggleDeckButton->ButtonPressed()) + return ((toggleDeckButton->ButtonPressed()) || (sellCardButton->ButtonPressed()) || (statsPrevButton->ButtonPressed()) || (filterButton->ButtonPressed()) + || (toggleViewButton->ButtonPressed()) ); - } +} void GameStateDeckViewer::setButtonState(bool state) { @@ -371,6 +317,7 @@ void GameStateDeckViewer::setButtonState(bool state) sellCardButton->setIsSelectionValid(state); statsPrevButton->setIsSelectionValid(state); filterButton->setIsSelectionValid(state); + toggleViewButton->setIsSelectionValid(state); } @@ -380,16 +327,37 @@ void GameStateDeckViewer::RenderButtons() sellCardButton->Render(); filterButton->Render(); statsPrevButton->Render(); + toggleViewButton->Render(); +} + +void GameStateDeckViewer::setupView(GameStateDeckViewer::AvailableView view, DeckDataWrapper *deck) +{ + SAFE_DELETE(mView); + + if(view == CAROUSEL_VIEW) mView = NEW CarouselDeckView(); + else if(view == GRID_VIEW) mView = NEW GridDeckView(); + + mView->SetDeck(deck); + updateFilters(); +} + +void GameStateDeckViewer::toggleView() +{ + if(mCurrentView == CAROUSEL_VIEW) + { + mCurrentView = GRID_VIEW; + toggleViewButton->setText("Carousel"); + } + else + { + mCurrentView = CAROUSEL_VIEW; + toggleViewButton->setText("Grid"); + } + setupView(mCurrentView, mView->deck()); } void GameStateDeckViewer::Update(float dt) -{ - - int x, y; - unsigned int distance2; - unsigned int minDistance2 = -1; - int n = 0; - +{ if (options.keypadActive()) { options.keypadUpdate(dt); @@ -418,7 +386,7 @@ void GameStateDeckViewer::Update(float dt) //Prevent screen from updating. return; } - hudAlpha = 255 - ((int) last_user_activity * 500); + hudAlpha = 255 - (int)(MAX(last_user_activity-2.0f, 0) * 500); if (hudAlpha < 0) hudAlpha = 0; if (subMenu) { @@ -431,27 +399,19 @@ void GameStateDeckViewer::Update(float dt) } if (mStage == STAGE_WAITING || mStage == STAGE_ONSCREEN_MENU) { - switch (mEngine->ReadButton()) + JButton button = mEngine->ReadButton(); + switch (button) { case JGE_BTN_LEFT: - last_user_activity = 0; - mStage = STAGE_TRANSITION_LEFT; - break; case JGE_BTN_RIGHT: - last_user_activity = 0; - mStage = STAGE_TRANSITION_RIGHT; - break; case JGE_BTN_UP: - last_user_activity = 0; - mStage = STAGE_TRANSITION_UP; - useFilter++; - if (useFilter >= MAX_SAVED_FILTERS) useFilter = 0; - break; case JGE_BTN_DOWN: - last_user_activity = 0; - mStage = STAGE_TRANSITION_DOWN; - useFilter--; - if (useFilter < 0) useFilter = MAX_SAVED_FILTERS - 1; + if(last_user_activity > 0.2) + { + mView->ButtonPressed(button); + last_user_activity = 0; + mStage = STAGE_WAITING; + } break; case JGE_BTN_CANCEL: options[Options::DISABLECARDS].number = !options[Options::DISABLECARDS].number; @@ -460,45 +420,44 @@ void GameStateDeckViewer::Update(float dt) if (last_user_activity > 0.2) { last_user_activity = 0; - switchDisplay(); + toggleCollection(); + } + break; + case JGE_BTN_MAX: + if (last_user_activity > 0.2) + { + last_user_activity = 0; + toggleView(); } break; case JGE_BTN_OK: + { + // verify that none of the buttons fired + if (userPressedButton()) + { + Update(dt); + break; + } + + int x, y; if (mEngine->GetLeftClickCoordinates(x, y)) { - // verify that none of the buttons fired - if (userPressedButton()) - { - Update(dt); - break; - } - - for(int i=0; i < CARDS_DISPLAYED; i++) - { - distance2 = static_cast((cardsCoordinates[i].second - y) * (cardsCoordinates[i].second - y) + (cardsCoordinates[i].first - x) * (cardsCoordinates[i].first - x)); - if (distance2 < minDistance2) - { - minDistance2 = distance2; - n = i; - } - } - - if(n != 2) - { - mSelected = n; - last_user_activity = 0; - mStage = STAGE_TRANSITION_SELECTED; - } + last_user_activity = 0; mEngine->LeftClickedProcessed(); + if(mView->Click(x, y) == mView->getActiveCard()) + { + addRemove(mView->getActiveCard()); + } } - - if(mStage != STAGE_TRANSITION_SELECTED && last_user_activity > .05) + else { last_user_activity = 0; - addRemove(cardIndex[2]); + addRemove(mView->getActiveCard()); } - + + mStage = STAGE_WAITING; break; + } case JGE_BTN_SEC: sellCard(); break; @@ -516,19 +475,19 @@ void GameStateDeckViewer::Update(float dt) SAFE_DELETE(source); source = NEW WSrcDeckViewer(myDeck, myCollection); filterMenu->setSrc(source); - if (displayed_deck != myDeck) source->swapSrc(); + if (mView->deck() != myDeck) source->swapSrc(); } filterMenu->Entering(JGE_BTN_NONE); break; case JGE_BTN_PREV: if (last_user_activity < NO_USER_ACTIVITY_HELP_DELAY) last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; - else if ((mStage == STAGE_ONSCREEN_MENU) && (--stw->currentPage < 0)) stw->currentPage = stw->pageCount; + else if ((mStage == STAGE_ONSCREEN_MENU) && (--mStatsWrapper->currentPage < 0)) mStatsWrapper->currentPage = mStatsWrapper->pageCount; break; case JGE_BTN_NEXT: if (last_user_activity < NO_USER_ACTIVITY_HELP_DELAY) last_user_activity = NO_USER_ACTIVITY_HELP_DELAY + 1; - else if ((mStage == STAGE_ONSCREEN_MENU) && (++stw->currentPage > stw->pageCount)) stw->currentPage = 0; + else if ((mStage == STAGE_ONSCREEN_MENU) && (++mStatsWrapper->currentPage > mStatsWrapper->pageCount)) mStatsWrapper->currentPage = 0; break; default: // no keypress if (last_user_activity > NO_USER_ACTIVITY_HELP_DELAY) @@ -548,111 +507,24 @@ void GameStateDeckViewer::Update(float dt) } else last_user_activity += dt; - + break; } } - if (mStage == STAGE_TRANSITION_SELECTED) - { - if (mSelected < 2) - { - mRotation -= dt * MED_SPEED; - if (mRotation < mSelected-2) - { - do - { - rotateCards(STAGE_TRANSITION_RIGHT); - mRotation += 1; - } while (mRotation < -1.0f); - mStage = STAGE_WAITING; - mRotation = 0; - } - } - else if (mSelected > 2) - { - mRotation += dt * MED_SPEED; - if (mRotation > mSelected - 2) - { - do - { - rotateCards(STAGE_TRANSITION_LEFT); - mRotation -= 1; - } while (mRotation > 1.0f); - mStage = STAGE_WAITING; - mRotation = 0; - } - } - } - if (mStage == STAGE_TRANSITION_RIGHT || mStage == STAGE_TRANSITION_LEFT) - { - if (mStage == STAGE_TRANSITION_RIGHT) - { - mRotation -= dt * MED_SPEED; - if (mRotation < -1.0f) - { - do - { - rotateCards(mStage); - mRotation += 1; - } while (mRotation < -1.0f); - mStage = STAGE_WAITING; - mRotation = 0; - } - } - else if (mStage == STAGE_TRANSITION_LEFT) - { - mRotation += dt * MED_SPEED; - if (mRotation > 1.0f) - { - do - { - rotateCards(mStage); - mRotation -= 1; - } while (mRotation > 1.0f); - mStage = STAGE_WAITING; - mRotation = 0; - } - } - } - if (mStage == STAGE_TRANSITION_DOWN || mStage == STAGE_TRANSITION_UP) - { - if (mStage == STAGE_TRANSITION_DOWN) - { - mSlide -= 0.05f; - if (mSlide < -1.0f) - { - updateFilters(); - loadIndexes(); - mSlide = 1; - } - else if (mSlide > 0 && mSlide < 0.05) - { - mStage = STAGE_WAITING; - mSlide = 0; - } - } - if (mStage == STAGE_TRANSITION_UP) - { - mSlide += 0.05f; - if (mSlide > 1.0f) - { - updateFilters(); - loadIndexes(); - mSlide = -1; - } - else if (mSlide < 0 && mSlide > -0.05) - { - mStage = STAGE_WAITING; - mSlide = 0; - } - } + mView->Update(dt); + if(mView->dirtyFilters) + { + updateFilters(); + mView->reloadIndexes(); + mView->dirtyFilters = false; } - else if (mStage == STAGE_WELCOME) + + if (mStage == STAGE_WELCOME) welcome_menu->Update(dt); else if (mStage == STAGE_MENU) - menu->Update(dt); + deckMenu->Update(dt); else if (mStage == STAGE_FILTERS) { JButton key = mEngine->ReadButton(); @@ -663,19 +535,20 @@ void GameStateDeckViewer::Update(float dt) //useFilter = 0; filterMenu->Finish(true); filterMenu->Update(dt); - loadIndexes(); + mView->reloadIndexes(); return; } if (!filterMenu->isFinished()) { filterMenu->CheckUserInput(key); filterMenu->Update(dt); + mView->reloadIndexes(); } else { mStage = STAGE_WAITING; updateFilters(); - loadIndexes(); + mView->reloadIndexes(); } } } @@ -689,16 +562,16 @@ void GameStateDeckViewer::renderOnScreenBasicInfo() float y = 0; int allCopies, nowCopies; - nowCopies = displayed_deck->getCount(WSrcDeck::FILTERED_COPIES); - allCopies = displayed_deck->getCount(WSrcDeck::UNFILTERED_COPIES); - WCardFilter * wc = displayed_deck->getFiltersRoot(); + nowCopies = mView->deck()->getCount(WSrcDeck::FILTERED_COPIES); + allCopies = mView->deck()->getCount(WSrcDeck::UNFILTERED_COPIES); + WCardFilter * wc = mView->deck()->getFiltersRoot(); if (wc) - sprintf(buffer, "%s %i of %i cards (%i unique)", (displayed_deck == myDeck) ? "DECK: " : " ", nowCopies, allCopies, - displayed_deck->getCount(WSrcDeck::FILTERED_UNIQUE)); + sprintf(buffer, "%s %i of %i cards (%i unique)", (mView->deck() == myDeck) ? "DECK: " : " ", nowCopies, allCopies, + mView->deck()->getCount(WSrcDeck::FILTERED_UNIQUE)); else - sprintf(buffer, "%s%i cards (%i unique)", (displayed_deck == myDeck) ? "DECK: " : " ", allCopies, displayed_deck->getCount( - WSrcDeck::UNFILTERED_UNIQUE)); + sprintf(buffer, "%s%i cards (%i unique)", (mView->deck() == myDeck) ? "DECK: " : " ", allCopies, + mView->deck()->getCount(WSrcDeck::UNFILTERED_UNIQUE)); float w = mFont->GetStringWidth(buffer); PIXEL_TYPE backupColor = mFont->GetColor(); @@ -708,34 +581,21 @@ void GameStateDeckViewer::renderOnScreenBasicInfo() mFont->DrawString(buffer, SCREEN_WIDTH - 22, y + 15, JGETEXT_RIGHT); mFont->SetColor(backupColor); - if (useFilter != 0) renderer->RenderQuad(mIcons[useFilter - 1].get(), SCREEN_WIDTH - 10, y + 15, 0.0f, 0.5, 0.5); -} - -//returns position of the current card (cusor) in the currently viewed color/filter -int GameStateDeckViewer::getCurrentPos() -{ - int total = displayed_deck->Size(); - - int currentPos = displayed_deck->getOffset(); - currentPos += 2; //we start by displaying card number 3 - currentPos = currentPos % total + 1; - if (currentPos < 0) currentPos = (total + currentPos); - if (!currentPos) currentPos = total; - return currentPos; + if (mView->filter() != 0) renderer->RenderQuad(mIcons[mView->filter() - 1].get(), SCREEN_WIDTH - 10, y + 15, 0.0f, 0.5, 0.5); } void GameStateDeckViewer::renderSlideBar() { WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); - int total = displayed_deck->Size(); + int total = mView->deck()->Size(); if (total == 0) return; float filler = 15; float y = SCREEN_HEIGHT_F - 25; float bar_size = SCREEN_WIDTH_F - 2 * filler; JRenderer * r = JRenderer::GetInstance(); - int currentPos = getCurrentPos(); + int currentPos = mView->getPosition(); float cursor_pos = bar_size * currentPos / total; @@ -746,7 +606,7 @@ void GameStateDeckViewer::renderSlideBar() r->DrawLine(filler + cursor_pos, y, filler + cursor_pos, y + 5, ARGB(hudAlpha,255,255,255)); char buffer[256]; string deckname = _("Collection"); - if (displayed_deck == myDeck) + if (mView->deck() == myDeck) { deckname = _("Deck"); } @@ -785,9 +645,9 @@ void GameStateDeckViewer::renderDeckBackground() maxC2 = maxC1; } PIXEL_TYPE colors[] = { ARGB(255, Constants::_r[maxC1], Constants::_g[maxC1], Constants::_b[maxC1]), - ARGB(255, Constants::_r[maxC1], Constants::_g[maxC1], Constants::_b[maxC1]), - ARGB(255, Constants::_r[maxC2], Constants::_g[maxC2], Constants::_b[maxC2]), - ARGB(255, Constants::_r[maxC2], Constants::_g[maxC2], Constants::_b[maxC2]), }; + ARGB(255, Constants::_r[maxC1], Constants::_g[maxC1], Constants::_b[maxC1]), + ARGB(255, Constants::_r[maxC2], Constants::_g[maxC2], Constants::_b[maxC2]), + ARGB(255, Constants::_r[maxC2], Constants::_g[maxC2], Constants::_b[maxC2]), }; JRenderer::GetInstance()->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, colors); @@ -814,7 +674,7 @@ void GameStateDeckViewer::renderOnScreenMenu() bool renderPSPIcons = true; #endif - if (stw->currentPage == 0) + if (mStatsWrapper->currentPage == 0) { //FillRects r->FillRect(0 - (onScreenTransition * 84), 0, 84, SCREEN_HEIGHT, ARGB(128,0,0,0)); @@ -845,7 +705,7 @@ void GameStateDeckViewer::renderOnScreenMenu() font->DrawString(_("Toggle Images"), rightPspX - 35, rightPspY - 40); - if (displayed_deck == myCollection) + if (mView->deck() == myCollection) { font->DrawString(_("Add card"), rightPspX + 20, rightPspY - 15); font->DrawString(_("View Deck"), rightPspX - 20, rightPspY - 15, JGETEXT_RIGHT); @@ -860,7 +720,7 @@ void GameStateDeckViewer::renderOnScreenMenu() font->DrawString(_("menu"), SCREEN_WIDTH - 35 + rightTransition, SCREEN_HEIGHT - 15); font->DrawString(_("filter"), SCREEN_WIDTH - 95 + rightTransition, SCREEN_HEIGHT - 15); - if (displayed_deck == myCollection) + if (mView->deck() == myCollection) { font->DrawString(_("in: collection"), 5 - leftTransition, 5); font->DrawString(_("Use SQUARE to view your deck,"), SCREEN_WIDTH - 200 + rightTransition, 5); @@ -879,7 +739,7 @@ void GameStateDeckViewer::renderOnScreenMenu() // print stuff here about the editor commands float textYOffset = SCREEN_HEIGHT_F/2; font->DrawString(_("Click on the card image"), SCREEN_WIDTH - 200 + rightTransition, textYOffset - (2 * fH)); - if (displayed_deck == myCollection) + if (mView->deck() == myCollection) font->DrawString(_("to add card to deck."), SCREEN_WIDTH - 200 + rightTransition, textYOffset - fH); else font->DrawString(_("to remove card from deck."), SCREEN_WIDTH - 200 + rightTransition, textYOffset - fH); @@ -915,7 +775,7 @@ void GameStateDeckViewer::renderOnScreenMenu() } else { - stw->updateStats( myDeck );; + mStatsWrapper->updateStats( myDeck );; char buffer[300]; @@ -937,16 +797,16 @@ void GameStateDeckViewer::renderOnScreenMenu() graphColor = ARGB(200, 155, 155, 155); string STATS_TITLE_FORMAT = _("%i: %s"); - switch (stw->currentPage) + switch (mStatsWrapper->currentPage) { case 1: // Counts, price // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Statistics Summary").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Statistics Summary").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); posY = 30; posX = 180; - sprintf(buffer, _("Your Deck: %i cards").c_str(), stw->cardCount); + sprintf(buffer, _("Your Deck: %i cards").c_str(), mStatsWrapper->cardCount); font->DrawString(buffer, 20 + leftTransition, posY); posY += 10; @@ -978,34 +838,34 @@ void GameStateDeckViewer::renderOnScreenMenu() r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); font->DrawString(_("Lands"), 20 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countLands); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->countLands); font->DrawString(buffer, posX + leftTransition, posY); posY += 14; r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); font->DrawString(_("Creatures"), 20 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countCreatures); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->countCreatures); font->DrawString(buffer, posX + leftTransition, posY); posY += 14; r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); font->DrawString(_("Spells"), 20 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countSpells); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->countSpells); font->DrawString(buffer, posX + leftTransition, posY); posY += 10; font->DrawString(_("Instants"), 30 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countInstants); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->countInstants); font->DrawString(buffer, posX + leftTransition, posY); posY += 10; font->DrawString(_("Enchantments"), 30 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countEnchantments); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->countEnchantments); font->DrawString(buffer, posX + leftTransition, posY); posY += 10; font->DrawString(_("Sorceries"), 30 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->countSorceries); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->countSorceries); font->DrawString(buffer, posX + leftTransition, posY); //sprintf(buffer, "Artifacts: %i", stw->countArtifacts); //mFont->DrawString(buffer, 20, 123); @@ -1014,7 +874,7 @@ void GameStateDeckViewer::renderOnScreenMenu() r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); font->DrawString(_("Average converted mana cost"), 20 + leftTransition, posY); - sprintf(buffer, _("%2.2f").c_str(), stw->avgManaCost); + sprintf(buffer, _("%2.2f").c_str(), mStatsWrapper->avgManaCost); font->DrawString(buffer, posX + leftTransition, posY); posY += 14; @@ -1023,17 +883,17 @@ void GameStateDeckViewer::renderOnScreenMenu() posY += 10; font->DrawString(_("No land in 1st hand"), 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[0]); + sprintf(buffer, _("%2.2f%%").c_str(), mStatsWrapper->noLandsProbInTurn[0]); font->DrawString(buffer, posX + leftTransition, posY); posY += 10; font->DrawString(_("No land in 9 cards"), 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[2]); + sprintf(buffer, _("%2.2f%%").c_str(), mStatsWrapper->noLandsProbInTurn[2]); font->DrawString(buffer, posX + leftTransition, posY); posY += 10; font->DrawString(_("No creatures in 1st hand"), 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noCreaturesProbInTurn[0]); + sprintf(buffer, _("%2.2f%%").c_str(), mStatsWrapper->noCreaturesProbInTurn[0]); font->DrawString(buffer, posX + leftTransition, posY); // Playgame Statistics @@ -1043,25 +903,25 @@ void GameStateDeckViewer::renderOnScreenMenu() posY += 10; font->DrawString(_("Games played"), 30 + leftTransition, posY); - sprintf(buffer, _("%i").c_str(), stw->gamesPlayed); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->gamesPlayed); font->DrawString(buffer, posX + leftTransition, posY); posY += 10; font->DrawString(_("Victory ratio"), 30 + leftTransition, posY); - sprintf(buffer, _("%i%%").c_str(), stw->percentVictories); + sprintf(buffer, _("%i%%").c_str(), mStatsWrapper->percentVictories); font->DrawString(buffer, posX + leftTransition, posY); posY += 15; r->DrawLine(20 + leftTransition, posY - 1, posX + 40 + leftTransition, posY - 1, ARGB(128, 255, 255, 255)); font->DrawString(_("Total price (credits)"), 20 + leftTransition, posY); - sprintf(buffer, _("%i ").c_str(), stw->totalPrice); + sprintf(buffer, _("%i ").c_str(), mStatsWrapper->totalPrice); font->DrawString(buffer, posX + leftTransition, posY); r->DrawLine(20 + leftTransition, posY + 13, posX + 40 + leftTransition, posY + 13, ARGB(128, 255, 255, 255)); break; case 5: // Land statistics - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana production").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Mana production").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); font->DrawString(_("Counts of manasources per type and color:"), 20 + leftTransition, 30); @@ -1079,19 +939,19 @@ void GameStateDeckViewer::renderOnScreenMenu() // Horizontal table lines r->DrawLine(27 + leftTransition, posY - 20, 60 + (Constants::NB_Colors - 2) * 15 + leftTransition, posY - 20, - ARGB(128, 255, 255, 255)); + ARGB(128, 255, 255, 255)); r->DrawLine(27 + leftTransition, posY - 1, 60 + (Constants::NB_Colors - 2) * 15 + leftTransition, posY - 1, - ARGB(128, 255, 255, 255)); + ARGB(128, 255, 255, 255)); r->DrawLine(27 + leftTransition, 2 * 10 + posY + 12, 60 + (Constants::NB_Colors - 2) * 15 + leftTransition, 2 * 10 - + posY + 12, ARGB(128, 255, 255, 255)); + + posY + 12, ARGB(128, 255, 255, 255)); r->DrawLine(27 + leftTransition, 3 * 10 + posY + 14, 60 + (Constants::NB_Colors - 2) * 15 + leftTransition, 3 * 10 - + posY + 14, ARGB(128, 255, 255, 255)); + + posY + 14, ARGB(128, 255, 255, 255)); // Vertical table lines r->DrawLine(26 + leftTransition, posY - 20, 26 + leftTransition, 3 * 10 + posY + 14, ARGB(128, 255, 255, 255)); r->DrawLine(43 + leftTransition, posY - 20, 43 + leftTransition, 3 * 10 + posY + 14, ARGB(128, 255, 255, 255)); r->DrawLine(60 + leftTransition + (Constants::NB_Colors - 2) * 15, posY - 20, 60 + leftTransition - + (Constants::NB_Colors - 2) * 15, 3 * 10 + posY + 14, ARGB(128, 255, 255, 255)); + + (Constants::NB_Colors - 2) * 15, 3 * 10 + posY + 14, ARGB(128, 255, 255, 255)); font->DrawString(_("BL"), 27 + leftTransition, posY); font->DrawString(_("NB"), 27 + leftTransition, posY + 10); @@ -1102,7 +962,7 @@ void GameStateDeckViewer::renderOnScreenMenu() for (int j = 0; j < Constants::NB_Colors - 1; j++) { - curCount = stw->countBasicLandsPerColor[j]; + curCount = mStatsWrapper->countBasicLandsPerColor[j]; if(curCount == 0) { sprintf(buffer, "."); } else { @@ -1110,7 +970,7 @@ void GameStateDeckViewer::renderOnScreenMenu() } font->DrawString(buffer, 49 + leftTransition + j * 15, posY); - curCount = stw->countLandsPerColor[j]; + curCount = mStatsWrapper->countLandsPerColor[j]; if(curCount == 0) { sprintf(buffer, "."); } else { @@ -1118,7 +978,7 @@ void GameStateDeckViewer::renderOnScreenMenu() } font->DrawString(buffer, 49 + leftTransition + j * 15, posY + 10); - curCount = stw->countNonLandProducersPerColor[j]; + curCount = mStatsWrapper->countNonLandProducersPerColor[j]; if(curCount == 0) { sprintf(buffer, "."); } else { @@ -1126,7 +986,7 @@ void GameStateDeckViewer::renderOnScreenMenu() } font->DrawString(buffer, 49 + leftTransition + j * 15, posY + 20); - curCount = stw->countLandsPerColor[j] + stw->countBasicLandsPerColor[j] + stw->countNonLandProducersPerColor[j]; + curCount = mStatsWrapper->countLandsPerColor[j] + mStatsWrapper->countBasicLandsPerColor[j] + mStatsWrapper->countNonLandProducersPerColor[j]; if(curCount == 0) { sprintf(buffer, "."); } else { @@ -1147,7 +1007,7 @@ void GameStateDeckViewer::renderOnScreenMenu() break; case 6: // Land statistics - in symbols - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana production - in mana symbols").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Mana production - in mana symbols").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); font->DrawString(_("Total colored manasymbols in lands' production:"), 20 + leftTransition, 30); @@ -1155,25 +1015,25 @@ void GameStateDeckViewer::renderOnScreenMenu() totalProducedSymbols = 0; for (int i = 1; i < Constants::NB_Colors - 1; i++) { - totalProducedSymbols += stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i]; //!! Move to updatestats! + totalProducedSymbols += mStatsWrapper->countLandsPerColor[i] + mStatsWrapper->countBasicLandsPerColor[i]; //!! Move to updatestats! } posY = 50; for (int i = 1; i < Constants::NB_Colors - 1; i++) { - if (stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i] > 0) + if (mStatsWrapper->countLandsPerColor[i] + mStatsWrapper->countBasicLandsPerColor[i] > 0) { - sprintf(buffer, _("%i").c_str(), stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i]); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->countLandsPerColor[i] + mStatsWrapper->countBasicLandsPerColor[i]); font->DrawString(buffer, 20 + leftTransition, posY); - sprintf(buffer, _("(%i%%)").c_str(), (int) (100 * (float) (stw->countLandsPerColor[i] - + stw->countBasicLandsPerColor[i]) / totalProducedSymbols)); + sprintf(buffer, _("(%i%%)").c_str(), (int) (100 * (float) (mStatsWrapper->countLandsPerColor[i] + + mStatsWrapper->countBasicLandsPerColor[i]) / totalProducedSymbols)); font->DrawString(buffer, 33 + leftTransition, posY); posX = 72; - for (int j = 0; j < stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i]; j++) + for (int j = 0; j < mStatsWrapper->countLandsPerColor[i] + mStatsWrapper->countBasicLandsPerColor[i]; j++) { r->RenderQuad(mIcons[i].get(), posX + leftTransition, posY + 6, 0, 0.5, 0.5); posX += ((j + 1) % 10 == 0) ? 17 : 13; - if ((((j + 1) % 30) == 0) && (j < stw->countLandsPerColor[i] + stw->countBasicLandsPerColor[i] - 1)) + if ((((j + 1) % 30) == 0) && (j < mStatsWrapper->countLandsPerColor[i] + mStatsWrapper->countBasicLandsPerColor[i] - 1)) { posX = 72; posY += 15; @@ -1192,34 +1052,34 @@ void GameStateDeckViewer::renderOnScreenMenu() int (*countPerCostAndColor)[Constants::STATS_MAX_MANA_COST + 1][Constants::MTG_NB_COLORS + 1]; float avgCost; - switch (stw->currentPage) + switch (mStatsWrapper->currentPage) { // Nested switch on the same variable. Oh yes. case 2: // Total counts // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Mana cost detail").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); font->DrawString(_("Card counts per mana cost:"), 20 + leftTransition, 30); - avgCost = stw->avgManaCost; - countPerCost = &stw->countCardsPerCost; - countPerCostAndColor = &stw->countCardsPerCostAndColor; + avgCost = mStatsWrapper->avgManaCost; + countPerCost = &mStatsWrapper->countCardsPerCost; + countPerCostAndColor = &mStatsWrapper->countCardsPerCostAndColor; break; case 3: // Creature counts // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail - Creatures").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Mana cost detail - Creatures").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); font->DrawString(_("Creature counts per mana cost:"), 20 + leftTransition, 30); - avgCost = stw->avgCreatureCost; - countPerCost = &stw->countCreaturesPerCost; - countPerCostAndColor = &stw->countCreaturesPerCostAndColor; + avgCost = mStatsWrapper->avgCreatureCost; + countPerCost = &mStatsWrapper->countCreaturesPerCost; + countPerCostAndColor = &mStatsWrapper->countCreaturesPerCostAndColor; break; case 4: // Spell counts // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost detail - Spells").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Mana cost detail - Spells").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); font->DrawString(_("Non-creature spell counts per mana cost:"), 20 + leftTransition, 30); - avgCost = stw->avgSpellCost; - countPerCost = &stw->countSpellsPerCost; - countPerCostAndColor = &stw->countSpellsPerCostAndColor; + avgCost = mStatsWrapper->avgSpellCost; + countPerCost = &mStatsWrapper->countSpellsPerCost; + countPerCostAndColor = &mStatsWrapper->countSpellsPerCostAndColor; break; default: countPerCost = NULL; @@ -1241,22 +1101,22 @@ void GameStateDeckViewer::renderOnScreenMenu() // Horizontal table lines r->DrawLine(27 + leftTransition, posY - 20, 75 + (Constants::NB_Colors - 2) * 15 + leftTransition, posY - 20, - ARGB(128, 255, 255, 255)); + ARGB(128, 255, 255, 255)); r->DrawLine(27 + leftTransition, posY - 1, 75 + (Constants::NB_Colors - 2) * 15 + leftTransition, posY - 1, - ARGB(128, 255, 255, 255)); + ARGB(128, 255, 255, 255)); r->DrawLine(27 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, 75 + (Constants::NB_Colors - 2) - * 15 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, ARGB(128, 255, 255, 255)); + * 15 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, ARGB(128, 255, 255, 255)); // Vertical table lines r->DrawLine(26 + leftTransition, posY - 20, 26 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, - ARGB(128, 255, 255, 255)); + ARGB(128, 255, 255, 255)); r->DrawLine(41 + leftTransition, posY - 20, 41 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, - ARGB(128, 255, 255, 255)); + ARGB(128, 255, 255, 255)); r->DrawLine(58 + leftTransition, posY - 20, 58 + leftTransition, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, - ARGB(128, 255, 255, 255)); + ARGB(128, 255, 255, 255)); r->DrawLine(75 + leftTransition + (Constants::NB_Colors - 2) * 15, posY - 20, 75 + leftTransition - + (Constants::NB_Colors - 2) * 15, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, - ARGB(128, 255, 255, 255)); + + (Constants::NB_Colors - 2) * 15, Constants::STATS_MAX_MANA_COST * 10 + posY + 12, + ARGB(128, 255, 255, 255)); for (int i = 0; i <= Constants::STATS_MAX_MANA_COST; i++) { @@ -1270,7 +1130,7 @@ void GameStateDeckViewer::renderOnScreenMenu() font->DrawString(buffer, 64 + leftTransition + j * 15, posY); } r->FillRect(77.f + leftTransition + (Constants::NB_Colors - 2) * 15.0f, posY + 2.0f, (*countPerCost)[i] * 5.0f, - 8.0f, graphColor); + 8.0f, graphColor); posY += 10; } @@ -1288,13 +1148,13 @@ void GameStateDeckViewer::renderOnScreenMenu() case 8: // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Probabilities").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Probabilities").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); // No lands detail float graphScale, graphWidth; graphWidth = 100; - graphScale = (stw->noLandsProbInTurn[0] == 0) ? 0 : (graphWidth / stw->noLandsProbInTurn[0]); + graphScale = (mStatsWrapper->noLandsProbInTurn[0] == 0) ? 0 : (graphWidth / mStatsWrapper->noLandsProbInTurn[0]); font->DrawString(_("No lands in first n cards:"), 20 + leftTransition, 30); posY = 50; @@ -1302,9 +1162,9 @@ void GameStateDeckViewer::renderOnScreenMenu() { sprintf(buffer, _("%i:").c_str(), i + 7); font->DrawString(buffer, 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noLandsProbInTurn[i]); + sprintf(buffer, _("%2.2f%%").c_str(), mStatsWrapper->noLandsProbInTurn[i]); font->DrawString(buffer, 45 + leftTransition, posY); - r->FillRect(84 + leftTransition, posY + 2, graphScale * stw->noLandsProbInTurn[i], 8, graphColor); + r->FillRect(84 + leftTransition, posY + 2, graphScale * mStatsWrapper->noLandsProbInTurn[i], 8, graphColor); posY += 10; } @@ -1312,15 +1172,15 @@ void GameStateDeckViewer::renderOnScreenMenu() posY += 10; font->DrawString(_("No creatures in first n cards:"), 20 + leftTransition, posY); posY += 20; - graphScale = (stw->noCreaturesProbInTurn[0] == 0) ? 0 : (graphWidth / stw->noCreaturesProbInTurn[0]); + graphScale = (mStatsWrapper->noCreaturesProbInTurn[0] == 0) ? 0 : (graphWidth / mStatsWrapper->noCreaturesProbInTurn[0]); for (int i = 0; i < Constants::STATS_FOR_TURNS; i++) { sprintf(buffer, _("%i:").c_str(), i + 7); font->DrawString(buffer, 30 + leftTransition, posY); - sprintf(buffer, _("%2.2f%%").c_str(), stw->noCreaturesProbInTurn[i]); + sprintf(buffer, _("%2.2f%%").c_str(), mStatsWrapper->noCreaturesProbInTurn[i]); font->DrawString(buffer, 45 + leftTransition, posY); - r->FillRect(84 + leftTransition, posY + 2, graphScale * stw->noCreaturesProbInTurn[i], 8, graphColor); + r->FillRect(84 + leftTransition, posY + 2, graphScale * mStatsWrapper->noCreaturesProbInTurn[i], 8, graphColor); posY += 10; } @@ -1328,7 +1188,7 @@ void GameStateDeckViewer::renderOnScreenMenu() case 7: // Total mana cost per color // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Mana cost per color").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Mana cost per color").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); font->DrawString(_("Total colored manasymbols in cards' casting costs:"), 20 + leftTransition, 30); @@ -1336,18 +1196,18 @@ void GameStateDeckViewer::renderOnScreenMenu() posY = 50; for (int i = 1; i < Constants::NB_Colors - 1; i++) { - if (stw->totalCostPerColor[i] > 0) + if (mStatsWrapper->totalCostPerColor[i] > 0) { - sprintf(buffer, _("%i").c_str(), stw->totalCostPerColor[i]); + sprintf(buffer, _("%i").c_str(), mStatsWrapper->totalCostPerColor[i]); font->DrawString(buffer, 20 + leftTransition, posY); - sprintf(buffer, _("(%i%%)").c_str(), (int) (100 * (float) stw->totalCostPerColor[i] / stw->totalColoredSymbols)); + sprintf(buffer, _("(%i%%)").c_str(), (int) (100 * (float) mStatsWrapper->totalCostPerColor[i] / mStatsWrapper->totalColoredSymbols)); font->DrawString(buffer, 33 + leftTransition, posY); posX = 72; - for (int j = 0; j < stw->totalCostPerColor[i]; j++) + for (int j = 0; j < mStatsWrapper->totalCostPerColor[i]; j++) { r->RenderQuad(mIcons[i].get(), posX + leftTransition, posY + 6, 0, 0.5, 0.5); posX += ((j + 1) % 10 == 0) ? 17 : 13; - if ((((j + 1) % 30) == 0) && (j < stw->totalCostPerColor[i] - 1)) + if ((((j + 1) % 30) == 0) && (j < mStatsWrapper->totalCostPerColor[i] - 1)) { posX = 72; posY += 15; @@ -1360,14 +1220,14 @@ void GameStateDeckViewer::renderOnScreenMenu() case 9: // Victory statistics // Title - sprintf(buffer, STATS_TITLE_FORMAT.c_str(), stw->currentPage, _("Victory statistics").c_str()); + sprintf(buffer, STATS_TITLE_FORMAT.c_str(), mStatsWrapper->currentPage, _("Victory statistics").c_str()); font->DrawString(buffer, 10 + leftTransition, 10); font->DrawString(_("Victories against AI:"), 20 + leftTransition, 30); - sprintf(buffer, _("Games played: %i").c_str(), stw->gamesPlayed); + sprintf(buffer, _("Games played: %i").c_str(), mStatsWrapper->gamesPlayed); font->DrawString(buffer, 20 + leftTransition, 45); - sprintf(buffer, _("Victory ratio: %i%%").c_str(), stw->percentVictories); + sprintf(buffer, _("Victory ratio: %i%%").c_str(), mStatsWrapper->percentVictories); font->DrawString(buffer, 20 + leftTransition, 55); int AIsPerColumn = 19; @@ -1375,13 +1235,13 @@ void GameStateDeckViewer::renderOnScreenMenu() posX = 20; // ToDo: Multiple pages when too many AI decks are present - for (int i = 0; i < (int) stw->aiDeckStats.size(); i++) + for (int i = 0; i < (int) mStatsWrapper->aiDeckStats.size(); i++) { - sprintf(buffer, _("%.14s").c_str(), stw->aiDeckNames.at(i).c_str()); + sprintf(buffer, _("%.14s").c_str(), mStatsWrapper->aiDeckNames.at(i).c_str()); font->DrawString(buffer, posX + (i < 2 * AIsPerColumn ? leftTransition : rightTransition), posY); - sprintf(buffer, _("%i/%i").c_str(), stw->aiDeckStats.at(i)->victories, stw->aiDeckStats.at(i)->nbgames); + sprintf(buffer, _("%i/%i").c_str(), mStatsWrapper->aiDeckStats.at(i)->victories, mStatsWrapper->aiDeckStats.at(i)->nbgames); font->DrawString(buffer, posX + (i < AIsPerColumn ? leftTransition : rightTransition) + 80, posY); - sprintf(buffer, _("%i%%").c_str(), stw->aiDeckStats.at(i)->percentVictories()); + sprintf(buffer, _("%i%%").c_str(), mStatsWrapper->aiDeckStats.at(i)->percentVictories()); font->DrawString(buffer, posX + (i < AIsPerColumn ? leftTransition : rightTransition) + 110, posY); posY += 10; if (((i + 1) % AIsPerColumn) == 0) @@ -1395,152 +1255,17 @@ void GameStateDeckViewer::renderOnScreenMenu() } } - -void GameStateDeckViewer::renderCard(int id, float rotation) -{ - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); - MTGCard * card = cardIndex[id]; - - float max_scale = 0.96f; - float x_center_0 = 180; - float right_border = SCREEN_WIDTH + 180; - - float x_center = x_center_0 + cos((rotation + 8 - id) * M_PI / 12) * (right_border - x_center_0); - float scale = max_scale / 1.12f * cos((x_center - x_center_0) * 1.5f / (right_border - x_center_0)) + 0.2f * max_scale * cos( - cos((x_center - x_center_0) * 0.15f / (right_border - x_center_0))); - float x = x_center; // ; - - float y = (SCREEN_HEIGHT_F) / 2.0f + SCREEN_HEIGHT_F * mSlide * (scale + 0.2f); - - cardsCoordinates[id] = pair(x, y); - - int alpha = (int) (255 * (scale + 1.0 - max_scale)); - - if (!card) return; - - if (!WResourceManager::Instance()->IsThreaded()) - { - JQuadPtr backQuad = WResourceManager::Instance()->GetQuad(kGenericCardID); - JQuadPtr quad; - - int cacheError = CACHE_ERROR_NONE; - - if (!options[Options::DISABLECARDS].number) - { - quad = WResourceManager::Instance()->RetrieveCard(card, RETRIEVE_EXISTING); - cacheError = WResourceManager::Instance()->RetrieveError(); - if (!quad.get() && cacheError != CACHE_ERROR_404) - { - if (last_user_activity > (abs(2 - id) + 1) * NO_USER_ACTIVITY_SHOWCARD_DELAY) - quad = WResourceManager::Instance()->RetrieveCard(card); - else - { - quad = backQuad; - } - } - } - - if (quad.get()) - { - if (quad == backQuad) - { - quad->SetColor(ARGB(255,255,255,255)); - float _scale = scale * (285 / quad->mHeight); - JRenderer::GetInstance()->RenderQuad(quad.get(), x, y, 0.0f, _scale, _scale); - } - else - { - Pos pos = Pos(x, y, scale * 285 / 250, 0.0, 255); - CardGui::DrawCard(card, pos); - } - } - else - { - Pos pos = Pos(x, y, scale * 285 / 250, 0.0, 255); - CardGui::DrawCard(card, pos, DrawMode::kText); - } - } - else - { - int mode = !options[Options::DISABLECARDS].number ? DrawMode::kNormal : DrawMode::kText; - - Pos pos = Pos(x, y, scale * 285 / 250, 0.0, 255); - CardGui::DrawCard(card, pos, mode); - } - - int quadAlpha = alpha; - if (!displayed_deck->count(card)) quadAlpha /= 2; - quadAlpha = 255 - quadAlpha; - if (quadAlpha > 0) - { - JRenderer::GetInstance()->FillRect(x - scale * 100.0f, y - scale * 142.5f, scale * 200.0f, scale * 285.0f, - ARGB(quadAlpha,0,0,0)); - } - if (last_user_activity < 3) - { - int fontAlpha = alpha; - float qtY = y - 135 * scale; - float qtX = x + 40 * scale; - char buffer[4096]; - sprintf(buffer, "x%i", displayed_deck->count(card)); - WFont * font = mFont; - font->SetColor(ARGB(fontAlpha/2,0,0,0)); - JRenderer::GetInstance()->FillRect(qtX, qtY, font->GetStringWidth(buffer) + 6, 16, ARGB(fontAlpha/2,0,0,0)); - font->DrawString(buffer, qtX + 4, qtY + 4); - font->SetColor(ARGB(fontAlpha,255,255,255)); - font->DrawString(buffer, qtX + 2, qtY + 2); - font->SetColor(ARGB(255,255,255,255)); - } -} - -void GameStateDeckViewer::renderCard(int id) -{ - renderCard(id, 0); -} - void GameStateDeckViewer::Render() { setButtonState(false); - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0)); - if (displayed_deck == myDeck && mStage != STAGE_MENU) - renderDeckBackground(); - int order[3] = { 1, 2, 3 }; - if (mRotation < 0.5 && mRotation > -0.5) - { - order[1] = 3; - order[2] = 2; - } - else if (mRotation < -0.5) - { - order[0] = 3; - order[2] = 1; - } + if (mView->deck() == myDeck && mStage != STAGE_MENU) + renderDeckBackground(); - // even though we want to draw the cards in a particular z order for layering, we want to prefetch them - // in a different order, ie the center card should appear first, then the adjacent ones - if (WResourceManager::Instance()->IsThreaded()) - { - WResourceManager::Instance()->RetrieveCard(cardIndex[0]); - WResourceManager::Instance()->RetrieveCard(cardIndex[3]); - WResourceManager::Instance()->RetrieveCard(cardIndex[4]); - WResourceManager::Instance()->RetrieveCard(cardIndex[2]); - WResourceManager::Instance()->RetrieveCard(cardIndex[5]); - WResourceManager::Instance()->RetrieveCard(cardIndex[1]); - WResourceManager::Instance()->RetrieveCard(cardIndex[6]); - } + mView->Render(); - renderCard(6, mRotation); - renderCard(5, mRotation); - renderCard(4, mRotation); - renderCard(0, mRotation); - - for (int i = 0; i < 3; i++) - { - renderCard(order[i], mRotation); - } - - if (displayed_deck->Size() > 0) + if (mView->deck()->Size() > 0) { setButtonState(true); renderSlideBar(); @@ -1567,12 +1292,12 @@ void GameStateDeckViewer::Render() if (mStage == STAGE_MENU) { setButtonState(false); - menu->Render(); + deckMenu->Render(); } if (subMenu) subMenu->Render(); - if (filterMenu && !filterMenu->isFinished()) + if (filterMenu && !filterMenu->isFinished()) { setButtonState(false); filterMenu->Render(); @@ -1586,21 +1311,21 @@ void GameStateDeckViewer::Render() int GameStateDeckViewer::loadDeck(int deckid) { - if (!stw) + if (!mStatsWrapper) { DeckManager *deckManager = DeckManager::GetInstance(); - stw = deckManager->getExtendedStatsForDeckId( deckid, MTGCollection(), false ); + mStatsWrapper = deckManager->getExtendedStatsForDeckId( deckid, MTGCollection(), false ); } - stw->currentPage = 0; - stw->pageCount = 9; - stw->needUpdate = true; + mStatsWrapper->currentPage = 0; + mStatsWrapper->pageCount = 9; + mStatsWrapper->needUpdate = true; if (!playerdata) playerdata = NEW PlayerData(MTGCollection()); SAFE_DELETE(myCollection); myCollection = NEW DeckDataWrapper(playerdata->collection); myCollection->Sort(WSrcCards::SORT_ALPHA); - displayed_deck = myCollection; + mView->SetDeck(myCollection); char deckname[256]; sprintf(deckname, "deck%i.txt", deckid); @@ -1644,7 +1369,7 @@ int GameStateDeckViewer::loadDeck(int deckid) myDeck->Sort(WSrcCards::SORT_ALPHA); SAFE_DELETE(filterMenu); rebuildFilters(); - loadIndexes(); + mView->reloadIndexes(); return 1; } @@ -1685,9 +1410,9 @@ void GameStateDeckViewer::ButtonPressed(int controllerId, int controlId) SAFE_DELETE(myCollection); myCollection = NEW DeckDataWrapper(playerdata->collection); myCollection->Sort(WSrcCards::SORT_ALPHA); - displayed_deck = myCollection; + mView->SetDeck(myCollection); rebuildFilters(); - loadIndexes(); + mView->reloadIndexes(); mStage = STAGE_WELCOME; break; } @@ -1760,18 +1485,19 @@ void GameStateDeckViewer::ButtonPressed(int controllerId, int controlId) { case MENU_ITEM_YES: { - MTGCard * card = cardIndex[2]; + MTGCard * card = mView->getActiveCard(); if (card) { int rnd = (rand() % 25); + int price = pricelist->getSellPrice(card); playerdata->credits += price; price = price - (rnd * price) / 100; pricelist->setPrice(card->getMTGId(), price); playerdata->collection->remove(card->getMTGId()); - displayed_deck->Remove(card, 1); - displayed_deck->validate(); - stw->needUpdate = true; - loadIndexes(); + mView->deck()->Remove(card, 1); + mView->deck()->validate(); + mStatsWrapper->needUpdate = true; + mView->reloadIndexes(); } } case MENU_ITEM_NO: @@ -1783,7 +1509,7 @@ void GameStateDeckViewer::ButtonPressed(int controllerId, int controlId) /* to keep actions consistent across the different platforms, we need to branch the way swipes are interpreted. iOS5 changes - the way a swipe moves a document on the page. swipe down is to simulate dragging the page down instead of moving down + the way a swipe moves a document on the page. swipe down is to simulate dragging the page down instead of moving down on a page. */ void GameStateDeckViewer::OnScroll(int inXVelocity, int inYVelocity) @@ -1798,25 +1524,13 @@ void GameStateDeckViewer::OnScroll(int inXVelocity, int inYVelocity) { if(abs(inXVelocity) > 300) { - //determine how many cards to move, the faster the velocity the more cards to move. - // the display is setup so that there is a max of 2 cards to the left and 7 cards to the right - // of the current card. + //FIXME: this 500 is a bit arbitrary int numCards = (magnitude / 500) % 8; - int offset = 0; - if ( (numCards == 0) && magnitude) numCards = 7; - if ( !flickRight) - { - if (numCards > 1) - offset = 0; - } - else - offset = 2 + numCards; - - mEngine->LeftClickedProcessed(); - mEngine->LeftClicked(static_cast(cardsCoordinates[offset].first), static_cast(cardsCoordinates[offset].second)); - mEngine->HoldKey_NoRepeat(JGE_BTN_OK); + mView->changePosition(flickRight ? numCards : - numCards); } } else - mEngine->HoldKey_NoRepeat(flickUp ? JGE_BTN_UP : JGE_BTN_DOWN); + mView->changeFilter(flickUp ? 1 : -1); + + last_user_activity = 0; } diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index c2b4174da..878415184 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -14,6 +14,7 @@ #include "Translate.h" #include "Rules.h" #include "ModRules.h" +#include "GameApp.h" #ifdef TESTSUITE #include "TestSuiteAI.h" diff --git a/projects/mtg/src/GameStateShop.cpp b/projects/mtg/src/GameStateShop.cpp index 2b780f5c7..34ddfa558 100644 --- a/projects/mtg/src/GameStateShop.cpp +++ b/projects/mtg/src/GameStateShop.cpp @@ -259,8 +259,8 @@ void GameStateShop::cancelCard(int controlId) break; } price = price - (rnd * price) / 100; - if (price < pricelist->getPrice(c->getMTGId())) //filters have a tendancy to increase the price instead of lowering it! - pricelist->setPrice(c->getMTGId(), price); + if (price < pricelist->getPrice(c)) //filters have a tendancy to increase the price instead of lowering it! + pricelist->setPrice(c, price); //Prices do not immediately go down when you ignore something. return; } diff --git a/projects/mtg/src/GridDeckView.cpp b/projects/mtg/src/GridDeckView.cpp new file mode 100644 index 000000000..1f976eab1 --- /dev/null +++ b/projects/mtg/src/GridDeckView.cpp @@ -0,0 +1,199 @@ +#include "GridDeckView.h" + +const float GridDeckView::scroll_animation_duration = 0.3f; +const float GridDeckView::slide_animation_duration = 0.6f; +const float GridDeckView::card_scale_small = 0.48f; +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) +{ + +} + +GridDeckView::~GridDeckView() +{ + +} + +void GridDeckView::Reset() +{ + mSlideEasing.finish(); + mScrollEasing.finish(); + + mCurrentSelection = 0; + + DeckView::Reset(); +} + +void GridDeckView::UpdateViewState(float dt) +{ + if(!mScrollEasing.finished()) + { + mScrollEasing.update(dt); + + if(mScrollOffset <= -1.0f) + { + SwitchPosition(2); + mScrollEasing.translate(1.0f); + mCurrentSelection = (mCurrentSelection >= 6) ? mCurrentSelection - 2 : -1; + } + else if(mScrollOffset >= 1.0f) + { + SwitchPosition(-2); + mScrollEasing.translate(-1.0f); + mCurrentSelection = (mCurrentSelection >= 0 && mCurrentSelection < 10) ? mCurrentSelection + 2 : -1; + } + + dirtyCardPos = true; + } + + if(!mSlideEasing.finished()) + { + mSlideEasing.update(dt); + + if(mSlideOffset < -1.0f) + { + mSlideEasing.translate(2.0f); + SwitchFilter(1); + } + else if(mSlideOffset > 1.0f) + { + mSlideEasing.translate(-2.0f); + SwitchFilter(-1); + } + + dirtyCardPos = true; + } +} + +void GridDeckView::UpdateCardPosition(CardRep &rep, int index) +{ + int col = index / mRows; + int row = index % mRows; + float colWidth = SCREEN_WIDTH_F / (mCols - 3); + float rowHeight = SCREEN_HEIGHT_F / mRows; + + rep.x = (col + mScrollOffset) * colWidth - colWidth; + rep.y = row * rowHeight + mSlideOffset*SCREEN_HEIGHT + rowHeight/2; + + if(mCurrentSelection == index) + { + rep.scale = card_scale_big; + if(row == 0) + { + rep.y += rowHeight * (card_scale_big - card_scale_small); + } + else + { + rep.y -= rowHeight * (card_scale_big - card_scale_small); + } + } + else + { + rep.scale = card_scale_small; + } +} + +void GridDeckView::Render() +{ + int firstVisibleCard = 2; + int lastVisibleCard = mCards.size() - 2; + + if(!mScrollEasing.finished()) + { + if(mScrollEasing.delta_value > 0){ + firstVisibleCard = 0; + } + else + { + lastVisibleCard = mCards.size(); + } + } + + for(int i = firstVisibleCard; i < lastVisibleCard; ++i) + { + + if(mCurrentSelection != i) + { + if (WResourceManager::Instance()->IsThreaded()) + { + WResourceManager::Instance()->RetrieveCard(getCardRep(i).card, RETRIEVE_THUMB); + } + renderCard(i, 255, true); + } + else + { + if (WResourceManager::Instance()->IsThreaded()) + { + WResourceManager::Instance()->RetrieveCard(getCardRep(i).card); + } + } + } + + if(2 <= mCurrentSelection && mCurrentSelection < 12) + { + renderCard(mCurrentSelection, 255, false); + } +} + +MTGCard * GridDeckView::Click(int x, int y) +{ + int n = getCardIndexNextTo(x, y); + last_user_activity = 0; + + if(mScrollEasing.finished() && mSlideEasing.finished()) + { //clicked and no animations running + if(n == mCurrentSelection) + { + return getActiveCard(); + } + else if(n < 4) + { + changePosition(-1); + } + else if(n >= 12) + { + changePosition(1); + } + else + { + mCurrentSelection = n; + dirtyCardPos = true; + } + } + + return NULL; +} + +void GridDeckView::changePosition(int offset) +{ + mScrollEasing.start(-1.0f * offset, scroll_animation_duration * abs(offset)); + last_user_activity = 0; +} + +void GridDeckView::changeFilter(int offset) +{ + if(offset < 0) + { + mSlideEasing.start(-2.0f, slide_animation_duration); + } + else if(offset > 0) + { + mSlideEasing.start(2.0f, slide_animation_duration); + } + last_user_activity = 0; +} + +MTGCard* GridDeckView::getActiveCard() +{ + if(mCurrentSelection >= 0 && mCurrentSelection < int(mCards.size())) + { + return mCards[mCurrentSelection].card; + } + else + { + return NULL; + } +} diff --git a/projects/mtg/src/GuiMana.cpp b/projects/mtg/src/GuiMana.cpp index 63d72936d..c4ca3d257 100644 --- a/projects/mtg/src/GuiMana.cpp +++ b/projects/mtg/src/GuiMana.cpp @@ -3,6 +3,7 @@ #include "GuiMana.h" #include "OptionItem.h" #include "Player.h" +#include "GameApp.h" //using std::cout; using std::endl; diff --git a/projects/mtg/src/OptionItem.cpp b/projects/mtg/src/OptionItem.cpp index df9edceab..4fee0a0ea 100644 --- a/projects/mtg/src/OptionItem.cpp +++ b/projects/mtg/src/OptionItem.cpp @@ -7,6 +7,7 @@ #include "TranslateKeys.h" #include "StyleManager.h" #include +#include "SimpleMenu.h" //OptionItem OptionItem::OptionItem(int _id, string _displayValue) : diff --git a/projects/mtg/src/PriceList.cpp b/projects/mtg/src/PriceList.cpp index 4e25d9c73..3586af28c 100644 --- a/projects/mtg/src/PriceList.cpp +++ b/projects/mtg/src/PriceList.cpp @@ -47,12 +47,12 @@ int PriceList::save() return 1; } -int PriceList::getPrice(int cardId) +int PriceList::getPrice(MTGCard * card) { - map::iterator it = prices.find(cardId); + map::iterator it = prices.find(card->getId()); if (it != prices.end()) return (*it).second; - char rarity = collection->getCardById(cardId)->getRarity(); + char rarity = card->getRarity(); switch (rarity) { case Constants::RARITY_M: @@ -77,7 +77,11 @@ int PriceList::getPrice(int cardId) return Constants::PRICE_1C; break; } +} +int PriceList::getPrice(int cardId) +{ + return getPrice(collection->getCardById(cardId)); } int PriceList::setPrice(int cardId, int price) @@ -85,10 +89,23 @@ int PriceList::setPrice(int cardId, int price) prices[cardId] = price; return price; } + +int PriceList::setPrice(MTGCard * card, int price) +{ + prices[card->getId()] = price; + return price; +} + int PriceList::getSellPrice(int cardid) { - return getPrice(cardid); + return getPrice(collection->getCardById(cardid)); } + +int PriceList::getSellPrice(MTGCard *card) +{ + return getPrice(card); +} + float PriceList::difficultyScalar(float price, int cardid) { float badluck = (float) (abs(cardid + randomKey) % 201) / 100; //Float between 0 and 2. diff --git a/projects/mtg/src/Rules.cpp b/projects/mtg/src/Rules.cpp index 9d7ed8ae9..b6e5e4d56 100644 --- a/projects/mtg/src/Rules.cpp +++ b/projects/mtg/src/Rules.cpp @@ -6,6 +6,7 @@ #include "Player.h" #include "AIMomirPlayer.h" +#include "GameApp.h" #include "MTGGameZones.h" #include "MTGAbility.h" #include "AllAbilities.h" diff --git a/projects/mtg/src/StoryFlow.cpp b/projects/mtg/src/StoryFlow.cpp index 98eacc5d7..8a6daed56 100644 --- a/projects/mtg/src/StoryFlow.cpp +++ b/projects/mtg/src/StoryFlow.cpp @@ -13,6 +13,7 @@ #include "PlayerData.h" #include "MTGDeck.h" #include "WFont.h" +#include "GameApp.h" #include #define LINE_SPACE 2 diff --git a/projects/mtg/src/WGui.cpp b/projects/mtg/src/WGui.cpp index 234b2c5a2..4a1308f1b 100644 --- a/projects/mtg/src/WGui.cpp +++ b/projects/mtg/src/WGui.cpp @@ -6,6 +6,9 @@ #include "Subtypes.h" #include "TranslateKeys.h" #include +#include "SimpleMenu.h" +#include "Pos.h" +#include "CardGui.h" /** Provides an interface to retrieve some standardized colors. The idea here is that a child of WGuiBase diff --git a/projects/mtg/template.vcxproj b/projects/mtg/template.vcxproj index 9fe22b571..912ece289 100644 --- a/projects/mtg/template.vcxproj +++ b/projects/mtg/template.vcxproj @@ -318,6 +318,12 @@ + + NotUsing + NotUsing + NotUsing + NotUsing + @@ -329,6 +335,12 @@ + + NotUsing + NotUsing + NotUsing + NotUsing + @@ -362,6 +374,12 @@ + + NotUsing + NotUsing + NotUsing + NotUsing + @@ -459,6 +477,7 @@ + @@ -471,7 +490,9 @@ + + @@ -486,6 +507,7 @@ + diff --git a/projects/mtg/template.vcxproj.filters b/projects/mtg/template.vcxproj.filters index 0d874bf5b..0e2cdef9e 100644 --- a/projects/mtg/template.vcxproj.filters +++ b/projects/mtg/template.vcxproj.filters @@ -331,6 +331,15 @@ src + + src + + + src + + + src + @@ -681,6 +690,18 @@ inc + + inc + + + inc + + + inc + + + inc + diff --git a/projects/mtg/wagic-SDL.pro b/projects/mtg/wagic-SDL.pro index 0855c80e5..39be85527 100644 --- a/projects/mtg/wagic-SDL.pro +++ b/projects/mtg/wagic-SDL.pro @@ -9,7 +9,7 @@ DEFINES += SDL_CONFIG # QT -= core gui opengl network declarative -unix|windows:QMAKE_CXXFLAGS += -std=c++11 +#unix|windows:QMAKE_CXXFLAGS += -std=c++11 INCLUDEPATH += ../../JGE/Dependencies/SDL/include unix:INCLUDEPATH += /usr/include/GL diff --git a/projects/mtg/wagic-qt.pro b/projects/mtg/wagic-qt.pro index 40c1eede5..487557c3f 100644 --- a/projects/mtg/wagic-qt.pro +++ b/projects/mtg/wagic-qt.pro @@ -49,9 +49,13 @@ CONFIG(graphics, graphics|console){ ../../JGE/src/pc/JGfx.cpp } else:CONFIG(console, graphics|console){ + HEADERS += \ + ../../JGE/include/OutputCapturer.h + SOURCES += \ + ../../JGE/src/OutputCapturer.cpp\ ../../JGE/src/JGfx-fake.cpp\ - ../../JGE/src/Qtconsole.cpp + ../../JGE/src/Qtconsole.cpp\ } # maemo 5 packaging diff --git a/projects/mtg/wagic.pri b/projects/mtg/wagic.pri index f5b4563eb..d797e9ebe 100644 --- a/projects/mtg/wagic.pri +++ b/projects/mtg/wagic.pri @@ -64,6 +64,7 @@ SOURCES += \ src/CardGui.cpp\ src/CardPrimitive.cpp\ src/CardSelector.cpp\ + src/CarouselDeckView.cpp\ src/Closest.cpp\ src/Counters.cpp\ src/Credits.cpp\ @@ -76,6 +77,7 @@ SOURCES += \ src/DeckMenuItem.cpp\ src/DeckMetaData.cpp\ src/DeckStats.cpp\ + src/DeckView.cpp\ src/DuelLayers.cpp\ src/Effects.cpp\ src/ExtraCost.cpp\ @@ -92,6 +94,7 @@ SOURCES += \ src/GameStateShop.cpp\ src/GameStateStory.cpp\ src/GameStateTransitions.cpp\ + src/GridDeckView.cpp\ src/GuiAvatars.cpp\ src/GuiBackground.cpp\ src/GuiCardsController.cpp\ @@ -159,6 +162,10 @@ SOURCES += \ src/TestSuiteAI.cpp HEADERS += \ + include/CarouselDeckView.h\ + include/DeckView.h\ + include/Easing.h\ + include/GridDeckView.h\ include/CacheEngine.h\ include/AllAbilities.h\ include/AbilityParser.h\ @@ -296,7 +303,6 @@ SOURCES += \ ../../JGE/src/pc/JSocket.cpp\ ../../JGE/src/pc/JSfx.cpp\ ../../JGE/src/JSprite.cpp\ - ../../JGE/src/OutputCapturer.cpp\ ../../JGE/src/Vector2D.cpp\ ../../JGE/src/tinyxml/tinystr.cpp\ ../../JGE/src/tinyxml/tinyxml.cpp\ @@ -344,7 +350,6 @@ HEADERS += \ ../../JGE/include/JSpline.h\ ../../JGE/include/JSprite.h\ ../../JGE/include/JTypes.h\ - ../../JGE/include/OutputCapturer.h\ ../../JGE/include/Vector2D.h\ ../../JGE/include/Vector3D.h\ ../../JGE/include/vram.h\