From 355ee7a271719429a045d1544fb06b4dff4f67c7 Mon Sep 17 00:00:00 2001 From: "wagic.jeck" Date: Wed, 26 Aug 2009 20:13:09 +0000 Subject: [PATCH] Jeck - Support for user profiles, preliminary theme support, virtual keypad, options GUI update. Still a bit unorganized, but it works. --- projects/mtg/Makefile | 176 ++-- projects/mtg/include/Credits.h | 6 +- projects/mtg/include/GameApp.h | 1 + projects/mtg/include/GameOptions.h | 91 +- projects/mtg/include/GameStateDeckViewer.h | 15 +- projects/mtg/include/GameStateDuel.h | 3 +- projects/mtg/include/GameStateMenu.h | 5 +- projects/mtg/include/GameStateOptions.h | 8 +- projects/mtg/include/OptionItem.h | 229 +++++- projects/mtg/include/PlayerData.h | 2 - projects/mtg/include/SimpleMenu.h | 5 - projects/mtg/include/SimplePad.h | 69 ++ projects/mtg/include/utils.h | 97 ++- projects/mtg/src/AIPlayer.cpp | 4 +- projects/mtg/src/Credits.cpp | 10 +- projects/mtg/src/DeckStats.cpp | 6 +- projects/mtg/src/GameApp.cpp | 4 +- projects/mtg/src/GameOptions.cpp | 357 +++++++- projects/mtg/src/GameStateDuel.cpp | 25 +- projects/mtg/src/GameStateMenu.cpp | 137 +-- projects/mtg/src/GameStateOptions.cpp | 343 ++++---- projects/mtg/src/GameStateShop.cpp | 2 +- projects/mtg/src/MenuItem.cpp | 5 +- projects/mtg/src/OptionItem.cpp | 914 ++++++++++++++++++--- projects/mtg/src/Player.cpp | 2 +- projects/mtg/src/PlayerData.cpp | 8 +- projects/mtg/src/ShopItem.cpp | 848 +++++++++---------- projects/mtg/src/SimpleMenu.cpp | 22 +- projects/mtg/src/SimplePad.cpp | 426 ++++++++++ projects/mtg/template.vcproj | 8 + 30 files changed, 2779 insertions(+), 1049 deletions(-) create mode 100644 projects/mtg/include/SimplePad.h create mode 100644 projects/mtg/src/SimplePad.cpp diff --git a/projects/mtg/Makefile b/projects/mtg/Makefile index 970b07f3c..a3766a908 100644 --- a/projects/mtg/Makefile +++ b/projects/mtg/Makefile @@ -1,88 +1,88 @@ -OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardSelector.o objs/ConstraintResolver.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DamageResolverLayer.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGGuiHand.o objs/MTGGuiPlay.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/TexturesCache.o objs/Token.o objs/Translate.o objs/utils.o objs/WEvent.o -DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS)) - -RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache) -ifeq ($(RESULT),) -DEFAULT_RULE = linux -TARGET_ARCHITECTURE = linux -TARGET = bin/wagic -else -DEFAULT_RULE = 3xx -TARGET_ARCHITECTURE = psp -PSPSDK = $(shell psp-config --pspsdk-path) -PSPDIR = $(shell psp-config --psp-prefix) -TARGET = wagic -endif -ifeq ($(MAKECMDGOALS),debug) -DEFAULT_RULE = debug -TARGET_ARCHITECTURE = linux -endif -ifeq ($(MAKECMDGOALS),linux) -DEFAULT_RULE = linux -TARGET_ARCHITECTURE = linux -endif - -ifeq ($(TARGET_ARCHITECTURE),psp) -DEFAULT_RULE = 3xx -TARGET_ARCHITECTURE = psp -PSP_FW_VERSION=371 -BUILD_PRX = 1 -LIBS = -ljge300 -lhgetools -lfreetype -ljpeg -lgif -lpng -lz -lm -lmikmod -lpsppower -lpspmpeg -lpspaudiocodec -lpspaudiolib -lpspaudio -lpspmp3 -lpspgum -lpspgu -lpsprtc -lstdc++ -lpspfpu - -EXTRA_TARGETS = EBOOT.PBP -PSP_EBOOT_TITLE = WTH?! -PSP_EBOOT_ICON = icon.png -CXXFLAGS = -O2 -G0 -Wall -DDEVHOOK -DPSPFW3XX -fno-exceptions -INCDIR = ../../JGE/include ../../JGE/include/psp ../../JGE/include/psp/freetype2 ../../JGE/src -LIBDIR = ../../JGE/lib/psp -else -OBJS += objs/TestSuiteAI.o -INCDIR = -I ../../JGE/include -I ../../JGE/src -LIBDIR = -L ../../JGE/lib/linux -L ../../JGE -LIBS = -ljge -lfreetype -ljpeg -lgif -lpng -lz -lm -lstdc++ -lglut -lhgetools -lfmod-3.75 -CFLAGS = $(INCDIR) -O2 -Wall -W -Werror -Wno-unused -DDEVHOOK -DLINUX -CXXFLAGS += $(CFLAGS) -fno-exceptions -ASFLAGS = $(CXXFLAGS) - -all: $(DEFAULT_RULE) - -endif - -LDFLAGS = $(LIBS) - - - -debug: CXXFLAGS = -Wall -W -Werror -Wno-unused -DDEVHOOK -DPSPFW3XX -fno-exceptions -ggdb3 -D_DEBUG -DDEBUG -DLINUX $(INCDIR) - - - - -ifeq ($(TARGET_ARCHITECTURE),psp) -include $(PSPSDK)/lib/build.mak - -3xx: - @echo Rule 3xx is deprecated. Did you want to use just "make" ? - -else - - - -$(TARGET): $(OBJS) ../../JGE/lib/linux/libjge.a - g++ -o $(TARGET) $(OBJS) $(LIBS) $(LIBDIR) - -linux: $(TARGET) - -debug: linux - -clean: - $(RM) $(OBJS) - -endif - -$(OBJS): objs/%.o: src/%.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $< - -$(DEPS): deps/%.d: src/%.cpp - @$(CXX) -MM $(CXXFLAGS) -MQ $(patsubst deps/%.d, objs/%.o, $(@)) -MQ $@ $< > $@ - --include $(DEPS) +OBJS = objs/ActionElement.o objs/ActionLayer.o objs/ActionStack.o objs/AIMomirPlayer.o objs/AIPlayer.o objs/AIStats.o objs/Blocker.o objs/CardGui.o objs/CardDescriptor.o objs/CardDisplay.o objs/CardEffect.o objs/CardSelector.o objs/ConstraintResolver.o objs/Counters.o objs/Credits.o objs/Damage.o objs/DamagerDamaged.o objs/DamageResolverLayer.o objs/DeckDataWrapper.o objs/DeckStats.o objs/DuelLayers.o objs/Effects.o objs/ExtraCost.o objs/GameApp.o objs/GameLauncher.o objs/GameObserver.o objs/GameOptions.o objs/GameState.o objs/GameStateDuel.o objs/GameStateMenu.o objs/GameStateOptions.o objs/GameStateShop.o objs/GuiAvatars.o objs/GuiBackground.o objs/GuiCardsController.o objs/GuiCombat.o objs/GuiFrame.o objs/GuiHand.o objs/GuiLayers.o objs/GuiMana.o objs/GuiPhaseBar.o objs/GuiPlay.o objs/GuiStatic.o objs/Logger.o objs/ManaCost.o objs/ManaCostHybrid.o objs/MenuItem.o objs/MTGAbility.o objs/MTGCardInstance.o objs/MTGCard.o objs/MTGDeck.o objs/MTGDefinitions.o objs/MTGGamePhase.o objs/MTGGameZones.o objs/MTGGuiHand.o objs/MTGGuiPlay.o objs/MTGRules.o objs/OptionItem.o objs/PhaseRing.o objs/Player.o objs/PlayerData.o objs/PlayGuiObjectController.o objs/PlayGuiObject.o objs/Pos.o objs/PriceList.o objs/ReplacementEffects.o objs/ShopItem.o objs/SimpleMenu.o objs/SimpleMenuItem.o objs/Subtypes.o objs/TargetChooser.o objs/TargetsList.o objs/TextScroller.o objs/TexturesCache.o objs/SimplePad.o objs/Token.o objs/Translate.o objs/utils.o objs/WEvent.o +DEPS = $(patsubst objs/%.o, deps/%.d, $(OBJS)) + +RESULT = $(shell psp-config --psp-prefix 2> Makefile.cache) +ifeq ($(RESULT),) +DEFAULT_RULE = linux +TARGET_ARCHITECTURE = linux +TARGET = bin/wagic +else +DEFAULT_RULE = 3xx +TARGET_ARCHITECTURE = psp +PSPSDK = $(shell psp-config --pspsdk-path) +PSPDIR = $(shell psp-config --psp-prefix) +TARGET = wagic +endif +ifeq ($(MAKECMDGOALS),debug) +DEFAULT_RULE = debug +TARGET_ARCHITECTURE = linux +endif +ifeq ($(MAKECMDGOALS),linux) +DEFAULT_RULE = linux +TARGET_ARCHITECTURE = linux +endif + +ifeq ($(TARGET_ARCHITECTURE),psp) +DEFAULT_RULE = 3xx +TARGET_ARCHITECTURE = psp +PSP_FW_VERSION=371 +BUILD_PRX = 1 +LIBS = -ljge300 -lhgetools -lfreetype -ljpeg -lgif -lpng -lz -lm -lmikmod -lpsppower -lpspmpeg -lpspaudiocodec -lpspaudiolib -lpspaudio -lpspmp3 -lpspgum -lpspgu -lpsprtc -lstdc++ -lpspfpu + +EXTRA_TARGETS = EBOOT.PBP +PSP_EBOOT_TITLE = WTH?! +PSP_EBOOT_ICON = icon.png +CXXFLAGS = -O2 -G0 -Wall -DDEVHOOK -DPSPFW3XX -fno-exceptions +INCDIR = ../../JGE/include ../../JGE/include/psp ../../JGE/include/psp/freetype2 ../../JGE/src +LIBDIR = ../../JGE/lib/psp +else +OBJS += objs/TestSuiteAI.o +INCDIR = -I ../../JGE/include -I ../../JGE/src +LIBDIR = -L ../../JGE/lib/linux -L ../../JGE +LIBS = -ljge -lfreetype -ljpeg -lgif -lpng -lz -lm -lstdc++ -lglut -lhgetools -lfmod-3.75 +CFLAGS = $(INCDIR) -O2 -Wall -W -Werror -Wno-unused -DDEVHOOK -DLINUX +CXXFLAGS += $(CFLAGS) -fno-exceptions +ASFLAGS = $(CXXFLAGS) + +all: $(DEFAULT_RULE) + +endif + +LDFLAGS = $(LIBS) + + + +debug: CXXFLAGS = -Wall -W -Werror -Wno-unused -DDEVHOOK -DPSPFW3XX -fno-exceptions -ggdb3 -D_DEBUG -DDEBUG -DLINUX $(INCDIR) + + + + +ifeq ($(TARGET_ARCHITECTURE),psp) +include $(PSPSDK)/lib/build.mak + +3xx: + @echo Rule 3xx is deprecated. Did you want to use just "make" ? + +else + + + +$(TARGET): $(OBJS) ../../JGE/lib/linux/libjge.a + g++ -o $(TARGET) $(OBJS) $(LIBS) $(LIBDIR) + +linux: $(TARGET) + +debug: linux + +clean: + $(RM) $(OBJS) + +endif + +$(OBJS): objs/%.o: src/%.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< + +$(DEPS): deps/%.d: src/%.cpp + @$(CXX) -MM $(CXXFLAGS) -MQ $(patsubst deps/%.d, objs/%.o, $(@)) -MQ $@ $< > $@ + +-include $(DEPS) diff --git a/projects/mtg/include/Credits.h b/projects/mtg/include/Credits.h index 61472399f..8037901dd 100644 --- a/projects/mtg/include/Credits.h +++ b/projects/mtg/include/Credits.h @@ -22,7 +22,7 @@ public: class Credits{ private: - int isDifficultyUnlocked(); + int isDifficultyUnlocked(); int isMomirUnlocked(); int isEvilTwinUnlocked(); int isRandomDeckUnlocked(); @@ -32,8 +32,8 @@ public: Player * p1, *p2; GameApp * app; int showMsg; - int unlocked; - JQuad * unlockedQuad; + int unlocked; + JQuad * unlockedQuad; JTexture * unlockedTex; string unlockedString; vector bonus; diff --git a/projects/mtg/include/GameApp.h b/projects/mtg/include/GameApp.h index 8dea131de..756734a67 100644 --- a/projects/mtg/include/GameApp.h +++ b/projects/mtg/include/GameApp.h @@ -26,6 +26,7 @@ #include "../include/GameState.h" +#include "../include/GameOptions.h" #include "../include/MTGDeck.h" #include "../include/MTGCard.h" diff --git a/projects/mtg/include/GameOptions.h b/projects/mtg/include/GameOptions.h index f6822b0ef..2745f9cfd 100644 --- a/projects/mtg/include/GameOptions.h +++ b/projects/mtg/include/GameOptions.h @@ -5,8 +5,14 @@ #include using std::map; using std::string; +#include +#include "../include/SimplePad.h" +#include "../include/GameApp.h" -#define OPTIONS_SAVEFILE RESPATH"/settings/options.txt" +#define GLOBAL_SETTINGS RESPATH"/settings/options.txt" +#define PLAYER_SAVEFILE "data.dat" +#define PLAYER_SETTINGS "options.txt" +#define PLAYER_COLLECTION "collection.dat" struct Options { static const string MUSICVOLUME; @@ -22,12 +28,52 @@ struct Options { static const string INTERRUPTMYSPELLS; static const string INTERRUPTMYABILITIES; static const string OSD; + static const string ACTIVE_PROFILE; + static const string ACTIVE_THEME; +}; + +struct Metrics { + //*_TC is text-color, *_TCH is highlighted text color + //*_FC is fill-color, *_FCH is highlighted fill color + //*_B and *_BH are for secondary text/fill colors, if needed + //*_X, *_Y, *_W, *_H are x, y, width and height. + static const string LOADING_TC; + static const string STATS_TC; + static const string SCROLLER_TC; + static const string SCROLLER_FC; + static const string MAINMENU_TC; + static const string POPUP_MENU_FC; + static const string POPUP_MENU_TC; + static const string POPUP_MENU_TCH; + static const string MSG_FAIL_TC; + static const string OPTION_ITEM_FC; + static const string OPTION_ITEM_TC; + static const string OPTION_ITEM_TCH; + static const string OPTION_HEADER_FC; + static const string OPTION_HEADER_TC; + static const string OPTION_SCROLLBAR_FC; + static const string OPTION_SCROLLBAR_FCH; + static const string OPTION_TAB_FC; + static const string OPTION_TAB_FCH; + static const string OPTION_TAB_TC; + static const string OPTION_TAB_TCH; + static const string OPTION_TEXT_TC; + static const string OPTION_TEXT_FC; + static const string KEY_TC; + static const string KEY_TCH; + static const string KEY_FC; + static const string KEY_FCH; + static const string KEYPAD_FC; + static const string KEYPAD_FCH; + static const string KEYPAD_TC; }; class GameOption { public: int number; string str; + //All calls to asColor should include a fallback color for people without a theme. + PIXEL_TYPE asColor(PIXEL_TYPE fallback = ARGB(255,255,255,255)); GameOption(int value = 0); GameOption(string value); }; @@ -35,18 +81,55 @@ public: class GameOptions { public: + string mFilename; int save(); int load(); + static const char * phaseInterrupts[]; GameOption& operator[](string); - GameOptions(); + GameOptions(string filename); ~GameOptions(); private: - static map optionsTypes; map values; }; -extern GameOptions options; +class GameSettings{ +public: + friend class GameApp; + GameSettings(); + ~GameSettings(); + int save(); + + SimplePad * keypadStart(string input, string * _dest = NULL, int _x = SCREEN_WIDTH/2, int _y = SCREEN_HEIGHT/2); + string keypadFinish(); + void keypadShutdown(); + void keypadTitle(string set); + bool keypadActive() {if(keypad) return keypad->isActive(); return false;}; + void keypadUpdate(float dt) {if(keypad) keypad->Update(dt);}; + void keypadRender() {if(keypad) keypad->Render();}; + + + //These return a filepath accurate to the current mode/profile/theme, and can + //optionally fallback to a file within a certain directory. + //The sanity=false option returns the adjusted path even if the file doesn't exist. + string profileFile(string filename="", string fallback="", bool sanity=true,bool relative=false); + string modeFile(string filename, string fallback, bool relative); + string themeGraphic(string filename); + + void checkProfile(); + void createUsersFirstDeck(int setId); + + GameOption& operator[](string); + GameOptions* profileOptions; + GameOptions* globalOptions; + GameOptions* themeOptions; + +private: + GameApp * theGame; + SimplePad * keypad; +}; + +extern GameSettings options; #endif diff --git a/projects/mtg/include/GameStateDeckViewer.h b/projects/mtg/include/GameStateDeckViewer.h index f6d9ebeea..3a92620cd 100644 --- a/projects/mtg/include/GameStateDeckViewer.h +++ b/projects/mtg/include/GameStateDeckViewer.h @@ -144,7 +144,7 @@ class GameStateDeckViewer: public GameState, public JGuiListener pricelist = NEW PriceList(RESPATH"/settings/prices.dat",mParent->collection); playerdata = NEW PlayerData(mParent->collection); sellMenu = NULL; - myCollection = NEW DeckDataWrapper(NEW MTGDeck(RESPATH"/player/collection.dat", &cache,mParent->collection)); + myCollection = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(PLAYER_COLLECTION,"",false).c_str(), &cache,mParent->collection)); displayed_deck = myCollection; myDeck = NULL; menuFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT); @@ -172,7 +172,7 @@ class GameStateDeckViewer: public GameState, public JGuiListener } - pspIconsTexture = JRenderer::GetInstance()->LoadTexture("graphics/iconspsp.png", TEX_TYPE_USE_VRAM); + pspIconsTexture = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("iconspsp.png").c_str(), TEX_TYPE_USE_VRAM); for (int i=0; i < 8; i++){ pspIcons[i] = NEW JQuad(pspIconsTexture, i*32, 0, 32, 32); @@ -184,7 +184,7 @@ class GameStateDeckViewer: public GameState, public JGuiListener //menuFont = NEW JLBFont("graphics/f3",16); menuFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); welcome_menu = NEW SimpleMenu(10,this,menuFont,20,20); - int nbDecks = fillDeckMenu(welcome_menu,RESPATH"/player"); + int nbDecks = fillDeckMenu(welcome_menu,options.profileFile()); welcome_menu->Add(nbDecks+1, "--NEW--"); welcome_menu->Add(-1, "Cancel"); @@ -726,12 +726,13 @@ class GameStateDeckViewer: public GameState, public JGuiListener int loadDeck(int deckid){ SAFE_DELETE(myCollection); - myCollection = NEW DeckDataWrapper(NEW MTGDeck(RESPATH"/player/collection.dat", &cache,mParent->collection)); + string profile = options[Options::ACTIVE_PROFILE].str; + myCollection = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(PLAYER_COLLECTION,"",false).c_str(), &cache,mParent->collection)); displayed_deck = myCollection; - char filename[4096]; - sprintf(filename, RESPATH"/player/deck%i.txt", deckid); + char deckname[256]; + sprintf(deckname,"deck%i.txt",deckid); SAFE_DELETE(myDeck); - myDeck = NEW DeckDataWrapper(NEW MTGDeck(filename, &cache,mParent->collection)); + myDeck = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(deckname).c_str(), &cache,mParent->collection)); MTGCard * current = myDeck->getNext(); while (current){ int howmanyinDeck = myDeck->cards[current]; diff --git a/projects/mtg/include/GameStateDuel.h b/projects/mtg/include/GameStateDuel.h index 012221e37..1b658bdfc 100644 --- a/projects/mtg/include/GameStateDuel.h +++ b/projects/mtg/include/GameStateDuel.h @@ -30,9 +30,8 @@ class GameStateDuel: public GameState, public JGuiListener SimpleMenu * deckmenu; SimpleMenu * opponentMenu; SimpleMenu * menu; + bool premadeDeck; JLBFont* mFont, *opponentMenuFont; - string playerDecksDir; - void loadPlayer(int playerId, int decknb = 0, int isAI = 0); void loadPlayerMomir(int playerId, int isAI); diff --git a/projects/mtg/include/GameStateMenu.h b/projects/mtg/include/GameStateMenu.h index 624230053..d61abd0d6 100644 --- a/projects/mtg/include/GameStateMenu.h +++ b/projects/mtg/include/GameStateMenu.h @@ -32,7 +32,7 @@ class GameStateMenu: public GameState, public JGuiListener DIR *mDip; struct dirent *mDit; - char mCurrentSetName[10]; + char mCurrentSetName[32]; char mCurrentSetFileName[512]; int mReadConf; @@ -52,7 +52,8 @@ class GameStateMenu: public GameState, public JGuiListener virtual void Render(); virtual void ButtonPressed(int controllerId, int controlId); - int nextCardSet(); // Retrieves the next set subfolder automatically + int nextDirectory(char * root, char * file); // Retrieves the next directory to have matching file + void resetDirectory(); void createUsersFirstDeck(int setId); virtual ostream& toString(ostream& out) const; }; diff --git a/projects/mtg/include/GameStateOptions.h b/projects/mtg/include/GameStateOptions.h index 59a15c2c0..fd137f8cd 100644 --- a/projects/mtg/include/GameStateOptions.h +++ b/projects/mtg/include/GameStateOptions.h @@ -6,10 +6,12 @@ #define SHOW_OPTIONS 1 #define SHOW_OPTIONS_MENU 2 +#define SHOW_OPTIONS_PROFILE 3 class GameApp; -class OptionsList; +class OptionsMenu; class SimpleMenu; +class SimplePad; class GameStateOptions: public GameState, public JGuiListener { @@ -18,8 +20,10 @@ private: public: SimpleMenu * optionsMenu; + SimpleMenu * confirmMenu; + OptionsMenu * optionsTabs; + int mState; - OptionsList * optionsList; GameStateOptions(GameApp* parent); virtual ~GameStateOptions(); diff --git a/projects/mtg/include/OptionItem.h b/projects/mtg/include/OptionItem.h index f4e542f9f..dd820ba24 100644 --- a/projects/mtg/include/OptionItem.h +++ b/projects/mtg/include/OptionItem.h @@ -1,40 +1,189 @@ -#ifndef _OPTION_ITEM_H_ -#define _OPTION_ITEM_H_ - -#include -#include - -using std::string; - -class OptionItem:public JGuiObject{ - public: - string displayValue, id; - int value; - int hasFocus; - int maxValue, increment; - float x, y; - OptionItem(string _id, string _displayValue, int _maxValue = 1, int _increment = 1); - - virtual void Render(); - virtual void Update(float dt); - virtual void Entering(); - virtual bool Leaving(); - void setData(); - virtual void updateValue(){value+=increment; if (value>maxValue) value=0;}; - virtual ostream& toString(ostream& out) const; -}; - -class OptionsList{ - public: - OptionItem * options[20]; - int nbitems; - int current; - OptionsList(); - ~OptionsList(); - void Render(); - void Update(float dt); - void Add(OptionItem * item); - void save(); -}; - -#endif +#ifndef _OPTION_ITEM_H_ +#define _OPTION_ITEM_H_ + +#include +#include +#include +#include "../include/GameApp.h" + +using std::string; + +#define MAX_OPTION_TABS 5 +#define MAX_OPTION_ITEMS 20 +#define MAX_ONSCREEN_OPTIONS 8 +#define OPTION_CENTER 4 + +#define OPTIONS_SUBMODE_NORMAL 0 +#define OPTIONS_SUBMODE_RELOAD 1 +#define OPTIONS_SUBMODE_PROFILE 2 +#define OPTIONS_SUBMODE_MODE 3 +#define OPTIONS_SUBMODE_THEME 4 + +class OptionItem { +public: + string displayValue, id; + int hasFocus; + bool canSelect; + float x, y; + float width, height; + virtual ostream& toString(ostream& out)const; + + OptionItem( string _id, string _displayValue); + + virtual void Entering(); + virtual bool Leaving(); + virtual void Update(float dt); + virtual void updateValue()=0; + virtual void Reload(){}; + virtual void Render()=0; + virtual void setData()=0; + virtual int Submode() {return OPTIONS_SUBMODE_NORMAL;}; + virtual void cancelSubmode() {}; + virtual void acceptSubmode() {}; +}; + +class OptionInteger:public OptionItem{ + public: + int value; + int maxValue, increment; + + OptionInteger(string _id, string _displayValue, int _maxValue = 1, int _increment = 1); + + virtual void Reload() {if(id != "") value = options[id].number;}; + virtual void Render(); + virtual void setData(); + virtual void updateValue(){value+=increment; if (value>maxValue) value=0;}; + virtual ostream& toString(ostream& out) const; +}; + +class OptionString:public OptionItem{ + public: + string value; + OptionString(string _id, string _displayValue); + + virtual void Render(); + virtual void setData(); + virtual void updateValue(); + virtual void Reload() {if(id != "") value = options[id].str;}; + virtual ostream& toString(ostream& out) const; + bool bShowValue; +}; +class OptionNewProfile:public OptionString{ + public: + OptionNewProfile(string _id, string _displayValue) : OptionString(_id, _displayValue) {bShowValue=false;}; + virtual void updateValue(); + virtual void Update(float dt); + virtual int Submode(); + bool bChanged; +}; + +class OptionHeader:public OptionItem{ + public: + OptionHeader(string _displayValue): OptionItem("", _displayValue) { canSelect=false;}; + virtual void Render(); + virtual void setData() {}; + virtual void updateValue() {}; +}; + +class OptionText:public OptionItem{ + public: + OptionText(string _displayValue): OptionItem("", _displayValue) { canSelect=false;}; + virtual void Render(); + virtual void setData() {}; + virtual void updateValue() {}; +}; + +class OptionSelect:public OptionItem{ + public: + int value; + vector selections; + + virtual void addSelection(string s); + OptionSelect(string _id, string _displayValue): OptionItem(_id, _displayValue) {value = 0;}; + virtual void Reload() {initSelections();}; + virtual void Render(); + virtual void setData(); + virtual void initSelections(); + virtual void updateValue(){value++; if (value > selections.size() - 1 || value < 0) value=0;}; + virtual ostream& toString(ostream& out) const; +}; + + +class OptionDirectory:public OptionSelect{ + public: + virtual void Reload(); + OptionDirectory(string _root, string _id, string _displayValue); +private: + string root; +}; + +class OptionProfile:public OptionDirectory{ + public: + OptionProfile(GameApp * _app); + ~OptionProfile(); + virtual void addSelection(string s); + virtual bool Leaving(); + virtual void Entering(); + virtual void Render(); + virtual void Update(float dt); + virtual void updateValue(); + virtual int Submode(); + virtual void cancelSubmode(); + virtual void acceptSubmode(); + void populate(); +private: + bool bCheck; + JQuad * mAvatar; + JTexture * mAvatarTex; + GameApp * app; + string preview; + int initialValue; +}; + +class OptionsList{ + public: + string sectionName; + string failMsg; + int nbitems; + int current; + OptionsList(string name); + ~OptionsList(); + bool Leaving(); + void Entering(); + void Render(); + void reloadValues(); + void Update(float dt); + void Add(OptionItem * item); + void save(); + int Submode(); + void acceptSubmode(); + void cancelSubmode(); + + OptionItem * operator[](int); +private: + OptionItem * listItems[MAX_OPTION_ITEMS]; +}; + +class OptionsMenu +{ + public: + OptionsList * tabs[MAX_OPTION_TABS]; + int nbitems; + int current; + + OptionsMenu(); + ~OptionsMenu(); + + bool isTab(string name); + int Submode(); + void acceptSubmode(); + void cancelSubmode(); + void Render(); + void reloadValues(); + void Update(float dt); + void Add(OptionsList * tab); + void save(); + +}; + +#endif diff --git a/projects/mtg/include/PlayerData.h b/projects/mtg/include/PlayerData.h index 003d63ea9..7f484cd8d 100644 --- a/projects/mtg/include/PlayerData.h +++ b/projects/mtg/include/PlayerData.h @@ -1,8 +1,6 @@ #ifndef _PLAYER_DATA_H_ #define _PLAYER_DATA_H_ -#define PLAYER_SAVEFILE RESPATH"/player/data.dat" - #include "../include/MTGDeck.h" class PlayerData{ diff --git a/projects/mtg/include/SimpleMenu.h b/projects/mtg/include/SimpleMenu.h index a987f4429..00fee6e8e 100644 --- a/projects/mtg/include/SimpleMenu.h +++ b/projects/mtg/include/SimpleMenu.h @@ -16,11 +16,6 @@ class SimpleMenu:public JGuiController{ static const unsigned VMARGIN; static const unsigned HMARGIN; static const signed LINE_HEIGHT; - static const char* spadeLPath; - static const char* spadeRPath; - static const char* jewelPath; - static const char* sidePath; - static const char* titleFontPath; private: int mHeight, mWidth, mX, mY; diff --git a/projects/mtg/include/SimplePad.h b/projects/mtg/include/SimplePad.h new file mode 100644 index 000000000..331a77805 --- /dev/null +++ b/projects/mtg/include/SimplePad.h @@ -0,0 +1,69 @@ +#ifndef _SIMPLEPAD_H_ +#define _SIMPLEPAD_H_ + +#include +#include +#include +#include "hge/hgeparticle.h" + +enum SIMPLE_KEYS{ + KPD_A, KPD_B, KPD_C, KPD_D, KPD_E, KPD_F, + KPD_G, KPD_H, KPD_I, KPD_J, KPD_K, KPD_L, + KPD_M, KPD_N, KPD_O, KPD_P, KPD_Q, KPD_R, + KPD_S, KPD_T, KPD_U, KPD_V, KPD_W, KPD_X, + KPD_Y, KPD_Z, KPD_SPACE, KPD_OK, KPD_CANCEL, + KPD_DEL, KPD_CAPS, KPD_0, KPD_1, KPD_2, KPD_3, + KPD_4, KPD_5, KPD_6, KPD_7, KPD_8, KPD_9, + KPD_MAX, + KPD_NOWHERE = 254, + KPD_INPUT = 255, +}; + +struct SimpleKey{ + SimpleKey( string _ds, int _id); + string displayValue; + unsigned char id; + unsigned char adjacency[4]; +}; + +class SimplePad{ +public: + friend class GameSettings; + + string buffer; + string title; + int cursorPos(); + bool isActive() {return bActive;}; + void Render(); + void Update(float dt); + void pressKey(unsigned char id); + + + + SimplePad(bool numbers=false); + ~SimplePad(); + + int mX; int mY; + +private: + void linkKeys(int from, int to, int dir); + SimpleKey * Add(string display, unsigned char id); + void MoveSelection(unsigned char dir); + void Start(string value, string * _dest=NULL); + string Finish(); + + bool bActive; + bool bCapslock; + bool bShowCancel, bShowNumpad; + bool bCanceled; + int nbitems; + int cursor; + int selected; + int priorKey; //The prior key from those places. + SimpleKey * keys[KPD_MAX]; + string * dest; + string original; //For cancelling. +}; + + +#endif diff --git a/projects/mtg/include/utils.h b/projects/mtg/include/utils.h index e875ee12c..375b97c38 100644 --- a/projects/mtg/include/utils.h +++ b/projects/mtg/include/utils.h @@ -1,46 +1,46 @@ -#ifndef _UTILS_H_ -#define _UTILS_H_ - -#include - -#if defined (WIN32) || defined (LINUX) - -#else -#include -#include -#include -#include -#include -#include -#include -#include +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include + +#if defined (WIN32) || defined (LINUX) + +#else +#include +#include +#include +#include +#include +#include +#include +#include #include -#include - -#endif - - -#include -#include -#include -#include -#include -#include -#include - - -using std::string; - - - -int filesize(const char * filename); -int fileExists(const char * filename); - -#ifdef LINUX -void dumpStack(); -#endif - +#include + +#endif + + +#include +#include +#include +#include +#include +#include +#include + + +using std::string; + + + +int filesize(const char * filename); +int fileExists(const char * filename); + +#ifdef LINUX +void dumpStack(); +#endif + /* RAM simple check functions header */ @@ -56,7 +56,14 @@ void dumpStack(); u32 ramAvailableLineareMax (void); u32 ramAvailable (void); - - -#endif - + +#ifdef WIN32 +#include +#define MAKEDIR(name) mkdir(name) +#else +#include +#define MAKEDIR(name) mkdir(name, 0777) +#endif + +#endif + diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index 868491c14..8be6906b6 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -555,8 +555,8 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * op if (deckid == -1){ //Evil twin sprintf(deckFile, opponent->deckFile.c_str()); - OutputDebugString(opponent->deckFile.c_str()); - sprintf(avatarFile, "player/avatar.jpg"); + OutputDebugString(opponent->deckFile.c_str()); + sprintf(avatarFile, "%s",options.profileFile("avatar.jpg","graphics",true,true).c_str()); sprintf(deckFileSmall, "ai_baka_eviltwin"); }else{ if (!deckid){ diff --git a/projects/mtg/src/Credits.cpp b/projects/mtg/src/Credits.cpp index ddff97fde..297f97e54 100644 --- a/projects/mtg/src/Credits.cpp +++ b/projects/mtg/src/Credits.cpp @@ -74,27 +74,27 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app){ if (unlocked == -1){ unlocked = isDifficultyUnlocked(); if (unlocked){ - unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/unlocked.png", TEX_TYPE_USE_VRAM); + unlockedTex = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("unlocked.png").c_str(), TEX_TYPE_USE_VRAM); unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96); options[Options::DIFFICULTY_MODE_UNLOCKED] = GameOption(1); options.save(); } else if ((unlocked = isMomirUnlocked())) { - unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/momir_unlocked.png", TEX_TYPE_USE_VRAM); + unlockedTex = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("momir_unlocked.png").c_str(), TEX_TYPE_USE_VRAM); unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96); options[Options::MOMIR_MODE_UNLOCKED] = GameOption(1); options.save(); } else if ((unlocked = isEvilTwinUnlocked())) { - unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/eviltwin_unlocked.png", TEX_TYPE_USE_VRAM); + unlockedTex = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("eviltwin_unlocked.png").c_str(), TEX_TYPE_USE_VRAM); unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96); options[Options::EVILTWIN_MODE_UNLOCKED] = GameOption(1); options.save(); }else if((unlocked = isRandomDeckUnlocked())) { - unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/randomdeck_unlocked.png", TEX_TYPE_USE_VRAM); + unlockedTex = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("randomdeck_unlocked.png").c_str(), TEX_TYPE_USE_VRAM); unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96); options[Options::RANDOMDECK_MODE_UNLOCKED] = GameOption(1); options.save(); }else if((unlocked = unlockRandomSet())) { - unlockedTex = JRenderer::GetInstance()->LoadTexture("graphics/set_unlocked.png", TEX_TYPE_USE_VRAM); + unlockedTex = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("set_unlocked.png").c_str(), TEX_TYPE_USE_VRAM); unlockedQuad = NEW JQuad(unlockedTex, 2, 2, 396, 96); char buffer[4096]; unlockedString = MtgSets::SetsList->values[unlocked -1]; diff --git a/projects/mtg/src/DeckStats.cpp b/projects/mtg/src/DeckStats.cpp index 1279005de..abb1c6dd1 100644 --- a/projects/mtg/src/DeckStats.cpp +++ b/projects/mtg/src/DeckStats.cpp @@ -67,7 +67,8 @@ int DeckStats::percentVictories(){ void DeckStats::load(Player * player){ char filename[512]; - sprintf(filename, RESPATH"/player/stats/%s.txt",player->deckFileSmall.c_str()); + sprintf(filename, RESPATH"/profile/%s/stats/%s.txt", + options[Options::ACTIVE_PROFILE].str.c_str(),player->deckFileSmall.c_str()); load(filename); } @@ -94,7 +95,8 @@ void DeckStats::load(const char * filename){ void DeckStats::save(Player * player){ char filename[512]; - sprintf(filename, RESPATH"/player/stats/%s.txt",player->deckFileSmall.c_str()); + sprintf(filename, RESPATH"/profile/%s/stats/%s.txt", + options[Options::ACTIVE_PROFILE].str.c_str(),player->deckFileSmall.c_str()); save(filename); } diff --git a/projects/mtg/src/GameApp.cpp b/projects/mtg/src/GameApp.cpp index 0ef8ea23a..551421960 100644 --- a/projects/mtg/src/GameApp.cpp +++ b/projects/mtg/src/GameApp.cpp @@ -62,6 +62,9 @@ void GameApp::Create() //_CrtSetBreakAlloc(368); LOG("starting Game"); + //Link this to our settings manager. + options.theGame = this; + //Test for Music files presence std::ifstream file(RESPATH"/sound/Track0.mp3"); if (file) @@ -168,7 +171,6 @@ void GameApp::Create() collection = NEW MTGAllCards(&cache); - Particles[0] = NEW hgeParticleSystem("graphics/particle1.psi", CommonRes->GetQuad("particles")); Particles[1] = NEW hgeParticleSystem("graphics/particle2.psi", CommonRes->GetQuad("particles")); Particles[2] = NEW hgeParticleSystem("graphics/particle3.psi", CommonRes->GetQuad("particles")); diff --git a/projects/mtg/src/GameOptions.cpp b/projects/mtg/src/GameOptions.cpp index dbdb603e4..d35d89910 100644 --- a/projects/mtg/src/GameOptions.cpp +++ b/projects/mtg/src/GameOptions.cpp @@ -1,4 +1,6 @@ #include "../include/config.h" +#include "../include/utils.h" +#include "../include/MTGDeck.h" #include "../include/GameOptions.h" #include #include @@ -22,37 +24,118 @@ const char* GameOptions::phaseInterrupts[] = { "interrupt Cleanup", "interrupt ---" }; +//Profile options const string Options::MUSICVOLUME = "musicVolume"; const string Options::SFXVOLUME = "sfxVolume"; -const string Options::DIFFICULTY_MODE_UNLOCKED = "prx_handler"; //huhu -const string Options::MOMIR_MODE_UNLOCKED = "prx_rimom"; //haha const string Options::DIFFICULTY = "difficulty"; -const string Options::CACHESIZE = "cacheSize"; const string Options::PLASMAEFFECT = "plasmaEffect"; const string Options::INTERRUPT_SECONDS = "interruptSeconds"; const string Options::INTERRUPTMYSPELLS = "interruptMySpells"; const string Options::INTERRUPTMYABILITIES = "interruptMyAbilities"; -const string Options::EVILTWIN_MODE_UNLOCKED = "prx_eviltwin"; -const string Options::RANDOMDECK_MODE_UNLOCKED = "prx_rnddeck"; const string Options::OSD = "displayOSD"; - +const string Options::ACTIVE_THEME = "Theme"; +//Global options +const string Options::ACTIVE_PROFILE = "_gProfile"; +const string Options::DIFFICULTY_MODE_UNLOCKED = "_gprx_handler"; //huhu +const string Options::MOMIR_MODE_UNLOCKED = "_gprx_rimom"; //haha +const string Options::EVILTWIN_MODE_UNLOCKED = "_gprx_eviltwin"; +const string Options::RANDOMDECK_MODE_UNLOCKED = "_gprx_rnddeck"; +const string Options::CACHESIZE = "_gcacheSize"; +//Theme metrics +const string Metrics::LOADING_TC = "_tLoadingTC"; +const string Metrics::STATS_TC = "_tStatsTC"; +const string Metrics::SCROLLER_TC = "_tScrollerTC"; +const string Metrics::SCROLLER_FC = "_tScrollerFC"; +const string Metrics::MAINMENU_TC = "_tMainMenuTC"; +const string Metrics::POPUP_MENU_FC = "_tPopupMenuFC"; +const string Metrics::POPUP_MENU_TC = "_tPopupMenuTC"; +const string Metrics::POPUP_MENU_TCH = "_tPopupMenuTCH"; +const string Metrics::MSG_FAIL_TC = "_tMsgFailTC"; +const string Metrics::OPTION_ITEM_FC = "_tOptionItemFC"; +const string Metrics::OPTION_ITEM_TC = "_tOptionItemTC"; +const string Metrics::OPTION_ITEM_TCH = "_tOptionItemTCH"; +const string Metrics::OPTION_HEADER_FC = "_tOptionHeaderFC"; +const string Metrics::OPTION_HEADER_TC = "_tOptionHeaderTC"; +const string Metrics::OPTION_SCROLLBAR_FC = "_tOptionScrollbarFC"; +const string Metrics::OPTION_SCROLLBAR_FCH = "_tOptionScrollbarFCH"; +const string Metrics::OPTION_TAB_FC = "_tOptionHeaderFC"; +const string Metrics::OPTION_TAB_FCH = "_tOptionHeaderFCH"; +const string Metrics::OPTION_TAB_TC = "_tOptionTabTC"; +const string Metrics::OPTION_TAB_TCH = "_tOptionHeaderTCH"; +const string Metrics::OPTION_TEXT_TC = "_tOptionTextTC"; +const string Metrics::OPTION_TEXT_FC = "_tOptionTextFC"; +const string Metrics::KEY_TC = "_tKeyTC"; +const string Metrics::KEY_TCH = "_tKeyTCH"; +const string Metrics::KEY_FC = "_tKeyFC"; +const string Metrics::KEY_FCH = "_tKeyFCH"; +const string Metrics::KEYPAD_FC = "_tKeypadFC"; +const string Metrics::KEYPAD_FCH = "_tKeypadFCH"; +const string Metrics::KEYPAD_TC = "_tKeypadTC"; GameOption::GameOption(int value) : number(value){} GameOption::GameOption(string value) : str(value){} -GameOptions::GameOptions(){ - load(); +PIXEL_TYPE GameOption::asColor(PIXEL_TYPE fallback) +{ + unsigned char color[4]; + string temp; + int subpixel=0; + + //The absolute shortest a color could be is 5 characters: "0,0,0" (implicit 255 alpha) + if(str.length() < 5) + return fallback; + + for(int i=0;i 3) + return fallback; + temp += str[i]; + } + + if(temp != "") + color[subpixel] = atoi(temp.c_str()); + if(subpixel == 2) + color[3] = 255; + + return ARGB(color[3],color[0],color[1],color[2]); } +GameOptions::GameOptions(string filename){ + mFilename = filename; + load(); +} int GameOptions::load(){ - std::ifstream file(OPTIONS_SAVEFILE); + std::ifstream file(mFilename.c_str()); std::string s; + if(file){ while(std::getline(file,s)){ int found =s.find("="); + bool bnumber = true; string name = s.substr(0,found); - values[name] = GameOption(atoi(s.substr(found+1).c_str())); + string val = s.substr(found+1); + for(int x=0;x::iterator it; for ( it=values.begin() ; it != values.end(); it++ ){ - sprintf(writer,"%s=%d\n", it->first.c_str(), it->second.number); + if(it->second.str ==""){ + sprintf(writer,"%s=%d\n", it->first.c_str(), it->second.number); + if(it->second.number==0) + continue; + } + else + sprintf(writer,"%s=%s\n", it->first.c_str(), it->second.str.c_str()); file<save(); + + if(profileOptions) + profileOptions->save(); + + SAFE_DELETE(globalOptions); + SAFE_DELETE(profileOptions); +} + +GameOption& GameSettings::operator[](string option_name){ + if(option_name.size() > 2){ + if(option_name[0] == '_' && option_name[1] == 't') + return (*themeOptions)[option_name.substr(2)]; + else if(option_name[0] == '_' && option_name[1] == 'g') + return (*globalOptions)[option_name.substr(2)]; + } + + return (*profileOptions)[option_name]; +} + +int GameSettings::save(){ + if(globalOptions) + globalOptions->save(); + + if(profileOptions) + profileOptions->save(); + + checkProfile(); + + return 1; +} + +string GameSettings::profileFile(string filename, string fallback,bool sanity, bool relative) +{ + char buf[512]; + string profile =(*this)[Options::ACTIVE_PROFILE].str; + + if(profile != "" && profile != "Default") { + //No file, return root of profile directory + if(filename == ""){ + sprintf(buf,"%sprofiles/%s",( relative ? "" : RESPATH"/" ),profile.c_str()); + return buf; + } + //Return file + sprintf(buf,RESPATH"/profiles/%s/%s",profile.c_str(),filename.c_str()); + if(fileExists(buf)){ + if(relative) + sprintf(buf,"profiles/%s/%s",profile.c_str(),filename.c_str()); + return buf; + } + } + else{ + //Use the default directory. + sprintf(buf,"%splayer%s%s",(relative ? "" : RESPATH"/"),(filename == "" ? "" : "/"), filename.c_str()); + return buf; + } + + //Don't fallback if sanity checking is disabled.. + if(!sanity){ + sprintf(buf,"%sprofiles/%s%s%s",(relative ? "" : RESPATH"/"),profile.c_str(),(filename == "" ? "" : "/"), filename.c_str()); + return buf; + } + + //No fallback directory. This is often a crash. + if(fallback == "") + return ""; + + sprintf(buf,"%s%s%s%s",(relative ? "" : RESPATH"/"),fallback.c_str(),(filename == "" ? "" : "/"), filename.c_str()); + return buf; +} + +string GameSettings::themeGraphic(string filename) +{ + char buf[4096]; + string theme = (*this)[Options::ACTIVE_THEME].str; + if(theme == "" || theme == "default"){ + sprintf(buf,"graphics/%s",filename.c_str()); + return buf; + } + + sprintf(buf,RESPATH"/themes/%s/%s",theme.c_str(),filename.c_str()); + + if(fileExists(buf)){ + sprintf(buf,"themes/%s/%s",theme.c_str(),filename.c_str()); + return buf; + } + + sprintf(buf,"graphics/%s",filename.c_str()); + return buf; +} + + +void GameSettings::checkProfile(){ + //Load current profile's options. Doesn't save prior set. + if(profileOptions != NULL) + SAFE_DELETE(profileOptions); + + string temp = profileFile("","",false,false); + MAKEDIR(temp.c_str()); + temp+="/stats"; + MAKEDIR(temp.c_str()); + temp = profileFile(PLAYER_SETTINGS,"",false); + profileOptions = new GameOptions(temp); + + //Validation of collection, etc, only happens if the game is up. + if(theGame == NULL || theGame->collection == NULL) + return; + + if(profileFile(PLAYER_COLLECTION) == "") + { + //If we had any default settings, we'd set them here. + + //Give the player cards from the set for which we have the most variety + int setId = 0; + int maxcards = 0; + for (int i=0; i< MtgSets::SetsList->nb_items; i++){ + int value = theGame->collection->countBySet(i); + if (value > maxcards){ + maxcards = value; + setId = i; + } + } + //Save this set as "unlocked" + char buffer[4096]; + string s = MtgSets::SetsList->values[setId]; + sprintf(buffer,"unlocked_%s", s.c_str()); + (*profileOptions)[buffer]=1; + profileOptions->save(); + createUsersFirstDeck(setId); + } +} + +void GameSettings::createUsersFirstDeck(int setId){ +#if defined (WIN32) || defined (LINUX) + char buf[4096]; + sprintf(buf, "setID: %i", setId); + OutputDebugString(buf); +#endif + + if(theGame == NULL || theGame->collection == NULL) + return; + + MTGDeck *mCollection = NEW MTGDeck(options.profileFile(PLAYER_COLLECTION,"",false).c_str(), &cache, theGame->collection); + //10 lands of each + int sets[] = {setId}; + if (!mCollection->addRandomCards(10, sets,1, Constants::RARITY_L,"Forest")){ + mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Forest"); + } + if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Plains")){ + mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Plains"); + } + if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Swamp")){ + mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Swamp"); + } + if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Mountain")){ + mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Mountain"); + } + if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Island")){ + mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Island"); + } + + +#if defined (WIN32) || defined (LINUX) + OutputDebugString("1\n"); +#endif + + //Starter Deck + mCollection->addRandomCards(3, sets,1,Constants::RARITY_R,NULL); + mCollection->addRandomCards(9, sets,1,Constants::RARITY_U,NULL); + mCollection->addRandomCards(48, sets,1,Constants::RARITY_C,NULL); + +#if defined (WIN32) || defined (LINUX) + OutputDebugString("2\n"); +#endif + //Boosters + for (int i = 0; i< 2; i++){ + mCollection->addRandomCards(1, sets,1,Constants::RARITY_R); + mCollection->addRandomCards(3, sets,1,Constants::RARITY_U); + mCollection->addRandomCards(11, sets,1,Constants::RARITY_C); + } + mCollection->save(); + SAFE_DELETE(mCollection); +} +void GameSettings::keypadTitle(string set){ + if(keypad != NULL) + keypad->title = set; +} +SimplePad * GameSettings::keypadStart(string input, string * _dest,int _x,int _y){ + if(keypad == NULL) + keypad = new SimplePad(); + keypad->mX = _x; + keypad->mY = _y; + keypad->Start(input,_dest); + return keypad; +} + +string GameSettings::keypadFinish(){ + if(keypad == NULL) + return ""; + return keypad->Finish(); +} + +void GameSettings::keypadShutdown(){ + SAFE_DELETE(keypad); +} \ No newline at end of file diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 72cbb754e..68f8d6c8b 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -42,7 +42,8 @@ GameStateDuel::GameStateDuel(GameApp* parent): GameState(parent) { deck[i]=NULL; mPlayers[i]=NULL; } - + + premadeDeck = false; game = NULL; deckmenu = NULL; opponentMenu = NULL; @@ -74,14 +75,10 @@ void GameStateDuel::Start() mGamePhase = DUEL_STATE_CHOOSE_DECK1; credits = NEW Credits(); - playerDecksDir = RESPATH"/player"; - mFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT); mFont->SetBase(0); opponentMenuFont = mFont; - - menu = NEW SimpleMenu(DUEL_MENU_GAME_MENU, this, mFont, SCREEN_WIDTH/2-100, 25); menu->Add(12,"Back to main menu"); menu->Add(13, "Cancel"); @@ -93,16 +90,16 @@ void GameStateDuel::Start() if (mParent->players[i] == PLAYER_TYPE_HUMAN){ decksneeded = 1; deckmenu = NEW SimpleMenu(DUEL_MENU_CHOOSE_DECK, this, mFont, 35, 25, "Choose a Deck"); - int nbDecks = fillDeckMenu(deckmenu,playerDecksDir); + int nbDecks = fillDeckMenu(deckmenu,options.profileFile()); if (nbDecks) decksneeded = 0; break; } } if (decksneeded){ - playerDecksDir = RESPATH"/player/premade"; deckmenu->Add(-1,"Create your Deck!","Highly recommended to get\nthe full Wagic experience!"); - fillDeckMenu(deckmenu,playerDecksDir); + premadeDeck = true; + fillDeckMenu(deckmenu,RESPATH"/player/premade"); } //mGamePhase = DUEL_STATE_ERROR_NO_DECK; } @@ -142,15 +139,14 @@ void GameStateDuel::loadPlayerRandom(int playerId, int isAI, int mode){ void GameStateDuel::loadPlayerMomir(int playerId, int isAI){ - char deckFile[] = RESPATH"/player/momir.txt"; string deckFileSmall = "momir"; char empty[] = ""; - MTGDeck * tempDeck = NEW MTGDeck(deckFile, NULL, mParent->collection); + MTGDeck * tempDeck = NEW MTGDeck(options.profileFile("momir.txt").c_str(), NULL, mParent->collection); deck[playerId] = NEW MTGPlayerCards(mParent->collection, tempDeck); if (!isAI) // Human Player - mPlayers[playerId] = NEW HumanPlayer(deck[playerId], deckFile, deckFileSmall); + mPlayers[playerId] = NEW HumanPlayer(deck[playerId], options.profileFile("momir.txt").c_str(), deckFileSmall); else - mPlayers[playerId] = NEW AIMomirPlayer(deck[playerId], deckFile, deckFileSmall, empty); + mPlayers[playerId] = NEW AIMomirPlayer(deck[playerId], options.profileFile("momir.txt").c_str(), deckFileSmall, empty); delete tempDeck; } @@ -158,7 +154,10 @@ void GameStateDuel::loadPlayer(int playerId, int decknb, int isAI){ if (decknb){ if (!isAI){ //Human Player char deckFile[255]; - sprintf(deckFile, "%s/deck%i.txt",playerDecksDir.c_str(), decknb); + if(premadeDeck) + sprintf(deckFile, RESPATH"/player/premade/deck%i.txt",decknb); + else + sprintf(deckFile, "%s/deck%i.txt",options.profileFile().c_str(), decknb); char deckFileSmall[255]; sprintf(deckFileSmall, "player_deck%i",decknb); MTGDeck * tempDeck = NEW MTGDeck(deckFile, NULL, mParent->collection); diff --git a/projects/mtg/src/GameStateMenu.cpp b/projects/mtg/src/GameStateMenu.cpp index 6bf735dd2..2cc63b4b2 100644 --- a/projects/mtg/src/GameStateMenu.cpp +++ b/projects/mtg/src/GameStateMenu.cpp @@ -26,7 +26,7 @@ enum ENUM_MENU_STATE_MAJOR MENU_STATE_MAJOR_LOADING_MENU = 0x03, MENU_STATE_MAJOR_LOADING_CARDS = 0x04, MENU_STATE_MAJOR_FIRST_TIME = 0x05, - MENU_STATE_MAJOR_DUEL = 0x07, + MENU_STATE_MAJOR_DUEL = 0x06, MENU_STATE_MAJOR = 0xFF }; @@ -83,13 +83,13 @@ void GameStateMenu::Create() mReadConf = 0; mCurrentSetName[0] = 0; - mIconsTexture = JRenderer::GetInstance()->LoadTexture("graphics/menuicons.png", TEX_TYPE_USE_VRAM); - bgTexture = JRenderer::GetInstance()->LoadTexture("graphics/menutitle.png", TEX_TYPE_USE_VRAM); - movingWTexture = JRenderer::GetInstance()->LoadTexture("graphics/movingW.png", TEX_TYPE_USE_VRAM); + mIconsTexture = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("menuicons.png").c_str(), TEX_TYPE_USE_VRAM); + bgTexture = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("menutitle.png").c_str(), TEX_TYPE_USE_VRAM); + movingWTexture = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("movingW.png").c_str(), TEX_TYPE_USE_VRAM); mBg = NEW JQuad(bgTexture, 0, 0, 256, 166); // Create background quad for rendering. mMovingW = NEW JQuad(movingWTexture, 2, 2, 84, 62); - if (fileExists("graphics/splash.jpg")){ - splashTex = JRenderer::GetInstance()->LoadTexture("graphics/splash.jpg", TEX_TYPE_USE_VRAM); + if (fileExists(options.themeGraphic("splash.jpg").c_str())){ + splashTex = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("splash.jpg").c_str(), TEX_TYPE_USE_VRAM); splashQuad = NEW JQuad(splashTex, 0, 0, 480, 272); } mBg->SetHotSpot(105,50); @@ -105,6 +105,7 @@ void GameStateMenu::Create() } JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT); + mFont->SetColor(options[Metrics::LOADING_TC].asColor()); mGuiController = NEW JGuiController(100, this); if (mGuiController) { @@ -173,9 +174,11 @@ void GameStateMenu::fillScroller(){ int totalGames = 0; for (int j=1; j<6; j++){ - sprintf(buffer, RESPATH"/player/stats/player_deck%i.txt",j); - if(fileExists(buffer)){ - stats->load(buffer); + + sprintf(buffer, "stats/player_deck%i.txt",j); + string deckstats = options.profileFile(buffer); + if(fileExists(deckstats.c_str())){ + stats->load(deckstats.c_str()); int percentVictories = stats->percentVictories(); sprintf(buff2, _("You have a %i%% victory ratio with Deck%i").c_str(),percentVictories,j); @@ -214,8 +217,7 @@ void GameStateMenu::fillScroller(){ sprintf(buff2, _("You have unlocked %i expansions out of %i").c_str(),nbunlocked, MtgSets::SetsList->nb_items); scroller->Add(buff2); - - DeckDataWrapper* ddw = NEW DeckDataWrapper(NEW MTGDeck(RESPATH"/player/collection.dat", &cache,mParent->collection)); + DeckDataWrapper* ddw = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(PLAYER_COLLECTION,"",false).c_str(), &cache,mParent->collection)); int totalCards = ddw->getCount(); if (totalCards){ sprintf(buff2, _("You have a total of %i cards in your collection").c_str(),totalCards); @@ -242,15 +244,20 @@ void GameStateMenu::fillScroller(){ scrollerSet = 1; scroller->setRandom(); } - -int GameStateMenu::nextCardSet(){ +void GameStateMenu::resetDirectory(){ + if(mDip != NULL) { + closedir(mDip); + mDip = NULL; + } +} +int GameStateMenu::nextDirectory(char * root, char * file){ int found = 0; if (!mDip){ - mDip = opendir(RESPATH"/sets/"); + mDip = opendir(root); } while (!found && (mDit = readdir(mDip))){ - sprintf(mCurrentSetFileName, RESPATH"/sets/%s/_cards.dat", mDit->d_name); + sprintf(mCurrentSetFileName, "%s/%s/%s", root, mDit->d_name, file); std::ifstream file(mCurrentSetFileName); if(file){ sprintf(mCurrentSetName, "%s", mDit->d_name); @@ -265,7 +272,6 @@ int GameStateMenu::nextCardSet(){ return found; } - void GameStateMenu::End() { @@ -286,41 +292,36 @@ void GameStateMenu::Update(float dt) }else{ mReadConf = 1; } - if (!nextCardSet()){ + if (!nextDirectory(RESPATH"/sets/","_cards.dat")){ //How many cards total ? sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards()); - //Check for first time comer - std::ifstream file(RESPATH"/player/collection.dat"); + + //Force default, if necessary. + if(options[Options::ACTIVE_PROFILE].str == "") + options[Options::ACTIVE_PROFILE].str = "Default"; + + //check for deleted collection / first-timer + std::ifstream file(options.profileFile(PLAYER_COLLECTION,"",false).c_str()); if(file){ file.close(); currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_NONE; }else{ - currentState = MENU_STATE_MAJOR_FIRST_TIME | MENU_STATE_MINOR_NONE; + //check for first time player! + file.open(options.profileFile(PLAYER_COLLECTION,"",false).c_str()); + if(file){ + file.close(); + currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_NONE; + }else{ + currentState = MENU_STATE_MAJOR_FIRST_TIME | MENU_STATE_MINOR_NONE; + } } + resetDirectory(); SAFE_DELETE(splashQuad); SAFE_DELETE(splashTex); } - break; + break; case MENU_STATE_MAJOR_FIRST_TIME : - { - //Give the player cards from the set for which we have the most variety - int setId = 0; - int maxcards = 0; - for (int i=0; i< MtgSets::SetsList->nb_items; i++){ - int value = mParent->collection->countBySet(i); - if (value > maxcards){ - maxcards = value; - setId = i; - } - } - //Save this set as "unlocked" - string s = MtgSets::SetsList->values[setId]; - char buffer[4096]; - sprintf(buffer,"unlocked_%s", s.c_str()); - options[buffer] = GameOption(1); - options.save(); - createUsersFirstDeck(setId); - } + options.checkProfile(); currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_NONE; break; case MENU_STATE_MAJOR_MAINMENU : @@ -395,54 +396,6 @@ void GameStateMenu::Update(float dt) -void GameStateMenu::createUsersFirstDeck(int setId){ -#if defined (WIN32) || defined (LINUX) - char buf[4096]; - sprintf(buf, "setID: %i", setId); - OutputDebugString(buf); -#endif - MTGDeck *mCollection = NEW MTGDeck(RESPATH"/player/collection.dat", &cache, mParent->collection); - //10 lands of each - int sets[] = {setId}; - if (!mCollection->addRandomCards(10, sets,1, Constants::RARITY_L,"Forest")){ - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Forest"); - } - if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Plains")){ - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Plains"); - } - if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Swamp")){ - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Swamp"); - } - if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Mountain")){ - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Mountain"); - } - if (!mCollection->addRandomCards(10, sets,1,Constants::RARITY_L,"Island")){ - mCollection->addRandomCards(10, 0,0,Constants::RARITY_L,"Island"); - } - - -#if defined (WIN32) || defined (LINUX) - OutputDebugString("1\n"); -#endif - - //Starter Deck - mCollection->addRandomCards(3, sets,1,Constants::RARITY_R,NULL); - mCollection->addRandomCards(9, sets,1,Constants::RARITY_U,NULL); - mCollection->addRandomCards(48, sets,1,Constants::RARITY_C,NULL); - -#if defined (WIN32) || defined (LINUX) - OutputDebugString("2\n"); -#endif - //Boosters - for (int i = 0; i< 2; i++){ - mCollection->addRandomCards(1, sets,1,Constants::RARITY_R); - mCollection->addRandomCards(3, sets,1,Constants::RARITY_U); - mCollection->addRandomCards(11, sets,1,Constants::RARITY_C); - } - mCollection->save(); - SAFE_DELETE(mCollection); -} - void GameStateMenu::Render() @@ -475,13 +428,13 @@ void GameStateMenu::Render() mGuiController->Render(); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); - mFont->SetColor(ARGB(128,255,255,255)); + mFont->SetColor(options[Metrics::STATS_TC].asColor(ARGB(128,255,255,255))); mFont->DrawString(GAME_VERSION, SCREEN_WIDTH-10,5,JGETEXT_RIGHT); mFont->DrawString(nbcardsStr,10, 5); mFont->SetScale(1.f); - mFont->SetColor(ARGB(255,255,255,255)); + mFont->SetColor(options[Metrics::SCROLLER_TC].asColor()); - renderer->FillRoundRect(SCREEN_WIDTH/2 - 100,SCREEN_HEIGHT-20, 191,6,5,ARGB(100,10,5,0)); + renderer->FillRoundRect(SCREEN_WIDTH/2 - 100,SCREEN_HEIGHT-20, 191,6,5,options[Metrics::SCROLLER_FC].asColor(ARGB(100,10,5,0))); scroller->Render(); if (subMenuController){ @@ -502,7 +455,7 @@ JLBFont * mFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT); #endif switch (controllerId){ case 101: - createUsersFirstDeck(controlId); + options.createUsersFirstDeck(controlId); currentState = MENU_STATE_MAJOR_MAINMENU | MENU_STATE_MINOR_NONE; break; default: diff --git a/projects/mtg/src/GameStateOptions.cpp b/projects/mtg/src/GameStateOptions.cpp index 0e52cffcd..7d0d298eb 100644 --- a/projects/mtg/src/GameStateOptions.cpp +++ b/projects/mtg/src/GameStateOptions.cpp @@ -1,139 +1,204 @@ -#include "../include/config.h" -#include "../include/GameStateOptions.h" -#include "../include/GameApp.h" -#include "../include/OptionItem.h" -#include "../include/SimpleMenu.h" -#include "../include/GameOptions.h" -#include "../include/Translate.h" - -GameStateOptions::GameStateOptions(GameApp* parent): GameState(parent) { - optionsList = NULL; - optionsMenu = NULL; -} - - -GameStateOptions::~GameStateOptions() { - -} - -void GameStateOptions::Start() -{ - - timer = 0; - mState = SHOW_OPTIONS; - JRenderer::GetInstance()->ResetPrivateVRAM(); - JRenderer::GetInstance()->EnableVSync(true); - - optionsList = NEW OptionsList(); - if (GameApp::HasMusic) optionsList->Add(NEW OptionItem(Options::MUSICVOLUME, "Music volume", 100, 10)); - optionsList->Add(NEW OptionItem(Options::SFXVOLUME, "SFX volume", 100, 10)); - optionsList->Add(NEW OptionItem(Options::INTERRUPTMYSPELLS, "interrupt my spells")); - optionsList->Add(NEW OptionItem(Options::INTERRUPTMYABILITIES, "interrupt my abilities")); - optionsList->Add(NEW OptionItem(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1)); - optionsList->Add(NEW OptionItem(Options::OSD, "Display InGame extra information")); - if (options[Options::DIFFICULTY_MODE_UNLOCKED].number) - optionsList->Add(NEW OptionItem(Options::DIFFICULTY, "Difficulty", 3, 1)); - optionsList->Add(NEW OptionItem(Options::CACHESIZE, "Image Cache Size", 60, 5)); - JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); - optionsMenu = NEW SimpleMenu(102, this,mFont, 50,170); - optionsMenu->Add(1, "Save & Back to Main Menu"); - optionsMenu->Add(2, "Back to Main Menu"); - optionsMenu->Add(3, "Cancel"); -} - - -void GameStateOptions::End() -{ - JRenderer::GetInstance()->EnableVSync(false); - SAFE_DELETE(optionsList); - SAFE_DELETE(optionsMenu); -} - - -void GameStateOptions::Update(float dt) -{ - - timer+= dt; - if (mState == SHOW_OPTIONS){ - if (PSP_CTRL_START == mEngine->ReadButton()){ - mState = SHOW_OPTIONS_MENU; - } - - optionsList->Update(dt); - }else{ - optionsMenu->Update(dt); - } - - -} - - -void GameStateOptions::Render() -{ - //Erase - JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0)); - - const char * const CreditsText[] = { - "Wagic, The Homebrew?! by wololo", - "", - "updates, new cards, and more on http://wololo.net/wagic", - "Many thanks to the devs and card creators who help this project", - "", - "Developped with the JGE++ Library (http://jge.khors.com)", - "", - "==Design & Art==", - "Shop, phase icons: Jhotun, http://www.jhotun.com/", - "Card back: Jeck", - "UI and some art by J", - "Player's avatar from http://mathieuchoinet.blogspot.com, under CC License", - "Background picture and some art from the KDE project, www.kde.org", - "SFX From www.soundsnap.com", - "Music by Celestial Aeon Project, http://www.jamendo.com", - "", - "", - "This work is not related to or endorsed by Wizards of the Coast, Inc", - "", - "Please support this project with donations at http://wololo.net/wagic", - }; - - - - JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/magic"); - mFont->SetColor(ARGB(255,200,200,200)); - mFont->SetScale(1.0); - float startpos = 272 - timer * 10; - float pos = startpos; - int size = sizeof(CreditsText) / sizeof(CreditsText[0]); - for (int i = 0; i < size; i++){ - pos = startpos +20*i; - if (pos > -20){ - mFont->DrawString(_(CreditsText[i]).c_str(),SCREEN_WIDTH/2,pos ,JGETEXT_CENTER); - } - } - - if (pos < -20) timer = 0; - mFont->SetScale(1.f); - - optionsList->Render(); - - if (mState == SHOW_OPTIONS_MENU){ - optionsMenu->Render(); - } -} - - -void GameStateOptions::ButtonPressed(int controllerId, int controlId) -{ - switch (controlId){ - case 1: - optionsList->save(); - case 2: - mParent->SetNextState(GAME_STATE_MENU); - break; - case 3: - mState = SHOW_OPTIONS; - break; - } -}; - - +#include "../include/config.h" +#include "../include/GameStateOptions.h" +#include "../include/GameApp.h" +#include "../include/OptionItem.h" +#include "../include/SimpleMenu.h" +#include "../include/SimplePad.h" +#include "../include/GameOptions.h" +#include "../include/Translate.h" + +GameStateOptions::GameStateOptions(GameApp* parent): GameState(parent) { + optionsTabs = NULL; + optionsMenu = NULL; + confirmMenu = NULL; +} + + +GameStateOptions::~GameStateOptions() { + +} + +void GameStateOptions::Start() +{ + + timer = 0; + mState = SHOW_OPTIONS; + JRenderer::GetInstance()->ResetPrivateVRAM(); + JRenderer::GetInstance()->EnableVSync(true); + + OptionsList * optionsList; + + optionsList = NEW OptionsList("Settings"); + + OptionProfile * pickProf = NEW OptionProfile(mParent); + optionsList->Add(pickProf); + OptionNewProfile * key = NEW OptionNewProfile("","New Profile"); + key->bShowValue = false; + optionsList->Add(key); + optionsList->Add(NEW OptionHeader("General Options")); + if (GameApp::HasMusic) optionsList->Add(NEW OptionInteger(Options::MUSICVOLUME, "Music volume", 100, 10)); + optionsList->Add(NEW OptionInteger(Options::SFXVOLUME, "SFX volume", 100, 10)); + optionsList->Add(NEW OptionInteger(Options::OSD, "Display InGame extra information")); + if (options[Options::DIFFICULTY_MODE_UNLOCKED].number) + optionsList->Add(NEW OptionInteger(Options::DIFFICULTY, "Difficulty", 3, 1)); + optionsList->Add(NEW OptionHeader("Interrupts")); + optionsList->Add(NEW OptionInteger(Options::INTERRUPT_SECONDS, "Seconds to pause for an Interrupt", 20, 1)); + optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYSPELLS, "Interrupt my spells")); + optionsList->Add(NEW OptionInteger(Options::INTERRUPTMYABILITIES, "Interrupt my abilities")); + optionsList->Add(NEW OptionHeader("System Options")); + optionsList->Add(NEW OptionInteger(Options::CACHESIZE, "Image Cache Size", 60, 5)); + optionsTabs = NEW OptionsMenu(); + optionsTabs->Add(optionsList); + optionsList = NEW OptionsList("Credits"); + optionsList->failMsg = ""; + optionsTabs->Add(optionsList); + + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + optionsMenu = NEW SimpleMenu(102, this,mFont, 50,170); + optionsMenu->Add(1, "Save & Back to Main Menu"); + optionsMenu->Add(2, "Back to Main Menu"); + optionsMenu->Add(3, "Cancel"); + + confirmMenu = NEW SimpleMenu(103, this,mFont, 50,170); + confirmMenu->Add(1, "Use this profile"); + confirmMenu->Add(2, "Cancel"); +} + + +void GameStateOptions::End() +{ + JRenderer::GetInstance()->EnableVSync(false); + SAFE_DELETE(optionsTabs); + SAFE_DELETE(optionsMenu); + SAFE_DELETE(confirmMenu); +} + + +void GameStateOptions::Update(float dt) +{ + + if(optionsTabs->isTab("Credits")) + timer += dt; + + if(options.keypadActive()){ + options.keypadUpdate(dt); + } + else if (mState == SHOW_OPTIONS){ + + switch(optionsTabs->Submode()){ + case OPTIONS_SUBMODE_RELOAD: + optionsTabs->acceptSubmode(); + optionsTabs->reloadValues(); + mState = SHOW_OPTIONS; + break; + case OPTIONS_SUBMODE_PROFILE: + mState = SHOW_OPTIONS_PROFILE; + break; + default: + if (PSP_CTRL_START == mEngine->ReadButton() ) + mState = SHOW_OPTIONS_MENU; + + optionsTabs->Update(dt); + break; + } + + }else if(mState == SHOW_OPTIONS_MENU){ + optionsMenu->Update(dt); + }else if(mState == SHOW_OPTIONS_PROFILE){ + confirmMenu->Update(dt); + } + + +} + +void GameStateOptions::Render() +{ + //Erase + JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0)); + + if(optionsTabs->isTab("Credits")){ + const char * const CreditsText[] = { + "Wagic, The Homebrew?! by WilLoW", + "", + "updates, new cards, and more on http://wololo.net/wagic", + "Many thanks to the devs and card creators who help this project", + "", + "Developped with the JGE++ Library (http://jge.khors.com)", + "Player's avatar from http://mathieuchoinet.blogspot.com, under CC License", + "Background picture and some art from the KDE project, www.kde.org", + "SFX From www.soundsnap.com", + "", + "Music by Celestial Aeon Project, http://www.jamendo.com", + "", + "", + "This work is not related to or endorsed by Wizards of the Coast, Inc", + "", + "Please support this project with donations at http://wololo.net/wagic", + }; + + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/magic"); + mFont->SetColor(ARGB(255,200,200,200)); + mFont->SetScale(1.0); + float startpos = 272 - timer * 10; + float pos = startpos; + int size = sizeof(CreditsText) / sizeof(CreditsText[0]); + + for (int i = 0; i < size; i++){ + pos = startpos +20*i; + if (pos > -20){ + mFont->DrawString(_(CreditsText[i]).c_str(),SCREEN_WIDTH/2,pos ,JGETEXT_CENTER); + } + } + + if (pos < -20) timer = 0; + mFont->SetScale(1.f); + } + + optionsTabs->Render(); + + switch(mState){ + case SHOW_OPTIONS_MENU: + optionsMenu->Render(); + break; + case SHOW_OPTIONS_PROFILE: + confirmMenu->Render(); + break; + } + + if(options.keypadActive()) + options.keypadRender(); +} + + +void GameStateOptions::ButtonPressed(int controllerId, int controlId) +{ + //Exit menu? + if(controllerId == 102) + switch (controlId){ + case 1: + optionsTabs->save(); + case 2: + mParent->SetNextState(GAME_STATE_MENU); + break; + case 3: + mState = SHOW_OPTIONS; + break; + } + //Profile confirmation? + else if(controllerId == 103) + switch (controlId){ + case 1: + //Load the new profile. + optionsTabs->acceptSubmode(); + optionsTabs->reloadValues(); + //Reset the current settings to those of the profile... + mState = SHOW_OPTIONS; + break; + case 2: + optionsTabs->cancelSubmode(); + mState = SHOW_OPTIONS; + break; + } +}; + + diff --git a/projects/mtg/src/GameStateShop.cpp b/projects/mtg/src/GameStateShop.cpp index 405d5b97f..b1216a5f1 100644 --- a/projects/mtg/src/GameStateShop.cpp +++ b/projects/mtg/src/GameStateShop.cpp @@ -36,7 +36,7 @@ void GameStateShop::Start() mStage = STAGE_SHOP_SHOP; - bgTexture = JRenderer::GetInstance()->LoadTexture("graphics/shop.jpg", TEX_TYPE_USE_VRAM); + bgTexture = JRenderer::GetInstance()->LoadTexture(options.themeGraphic("shop.jpg").c_str(), TEX_TYPE_USE_VRAM); mBg = NEW JQuad(bgTexture, 0, 0, 480, 272); // Create background quad for rendering. mBack = GameApp::CommonRes->GetQuad("back"); diff --git a/projects/mtg/src/MenuItem.cpp b/projects/mtg/src/MenuItem.cpp index 8dbdf38ff..f0b1c4248 100644 --- a/projects/mtg/src/MenuItem.cpp +++ b/projects/mtg/src/MenuItem.cpp @@ -1,5 +1,6 @@ #include "../include/config.h" #include "../include/MenuItem.h" +#include "../include/GameOptions.h" #include "../include/Translate.h" MenuItem::MenuItem(int id, JLBFont *font, string text, int x, int y, JQuad * _off, JQuad * _on, const char * particle, JQuad * particleTex, bool hasFocus): JGuiObject(id), mFont(font), mX(x), mY(y) @@ -24,10 +25,8 @@ MenuItem::MenuItem(int id, JLBFont *font, string text, int x, int y, JQuad * _of void MenuItem::Render() { - JRenderer * renderer = JRenderer::GetInstance(); - if (mHasFocus) { // set additive blending @@ -35,7 +34,7 @@ void MenuItem::Render() mParticleSys->Render(); // set normal blending renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - mFont->SetColor(ARGB(255,255,255,255)); + mFont->SetColor(options[Metrics::MAINMENU_TC].asColor()); onQuad->SetColor(ARGB(70,255,255,255)); renderer->RenderQuad(onQuad, SCREEN_WIDTH , SCREEN_HEIGHT/2 , 0,8,8); onQuad->SetColor(ARGB(255,255,255,255)); diff --git a/projects/mtg/src/OptionItem.cpp b/projects/mtg/src/OptionItem.cpp index bd0a85ed6..cb4134392 100644 --- a/projects/mtg/src/OptionItem.cpp +++ b/projects/mtg/src/OptionItem.cpp @@ -1,136 +1,778 @@ -#include "../include/OptionItem.h" -#include "../include/GameApp.h" -#include -#include "../include/GameOptions.h" -#include "../include/Translate.h" - -OptionItem::OptionItem(string _id, string _displayValue, int _maxValue, int _increment):JGuiObject(0){ - id = _id; - maxValue = _maxValue; - increment = _increment; - displayValue = _(_displayValue); - value = options[id].number; - hasFocus = 0; - x = 0; - y = 0; -} - -void OptionItem::setData(){ - options[id] = GameOption(value); -} - -void OptionItem::Render(){ - JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); - if (hasFocus){ - mFont->SetColor(ARGB(255,255,255,0)); - }else{ - mFont->SetColor(ARGB(255,255,255,255)); - } - JRenderer * renderer = JRenderer::GetInstance(); - renderer->FillRoundRect(x-5,y-2,SCREEN_WIDTH -x - 5,20,2,ARGB(150,50,50,50)); - mFont->DrawString(displayValue.c_str(),x,y); - char buf[512]; - if (maxValue == 1){ - if (value){ - sprintf(buf, _("Yes").c_str()); - }else{ - sprintf(buf,_("No").c_str()); - } - }else{ - sprintf(buf, "%i", value); - } - mFont->DrawString(buf,SCREEN_WIDTH -10 ,y,JGETEXT_RIGHT); -} - -void OptionItem::Update(float dt){ - JGE * mEngine = JGE::GetInstance(); - if (hasFocus){ - if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)) updateValue(); - } -} - - - -void OptionItem::Entering(){ - hasFocus = true; -} -bool OptionItem::Leaving(){ - hasFocus = false; - return true; -} - - -OptionsList::OptionsList(){ - nbitems = 0; - current = -1; -} -OptionsList::~OptionsList(){ - for (int i = 0 ; i < nbitems; i++){ - SAFE_DELETE(options[i]); - } -} - -void OptionsList::Add(OptionItem * item){ - if (nbitems < 20){ - options[nbitems] = item; - item->x = 10; - item->y = 20 + 30*nbitems; - nbitems++; - if (current < 0){ - current = 0; - options[0]->Entering(); - } - - } -} - -void OptionsList::Render(){ - if (!nbitems){ - JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); - mFont->DrawString("NO OPTIONS AVAILABLE",SCREEN_WIDTH/2, 5, JGETEXT_RIGHT); - } - for (int i = 0 ; i < nbitems; i++){ - options[i]->Render(); - } -} - -void OptionsList::save(){ - for (int i = 0; i < nbitems; i++){ - options[i]->setData(); - } - ::options.save(); -} - -void OptionsList::Update(float dt){ - JGE * mEngine = JGE::GetInstance(); - if (mEngine->GetButtonClick(PSP_CTRL_UP)) - { - if (current > 0){ - options[current]->Leaving(); - current--; - options[current]->Entering(); - } - } - else if (mEngine->GetButtonClick(PSP_CTRL_DOWN)) - { - if (current < nbitems -1){ - options[current]->Leaving(); - current++; - options[current]->Entering(); - } - } - for (int i = 0 ; i < nbitems; i++){ - options[i]->Update(dt); - } -} - -ostream& OptionItem::toString(ostream& out) const -{ - return out << "OptionItem ::: displayValue : " << displayValue - << " ; id : " << id - << " ; value : " << value - << " ; hasFocus : " << hasFocus - << " ; maxValue : " << maxValue - << " ; increment : " << increment - << " ; x,y : " << x << "," << y; -} +#include "../include/config.h" +#include "../include/OptionItem.h" +#include "../include/GameApp.h" +#include +#include "../include/GameOptions.h" +#include "../include/PlayerData.h" +#include "../include/Translate.h" +#include +#include +#include + +//Option Item + +void OptionItem::Update(float dt){ + JGE * mEngine = JGE::GetInstance(); + if (hasFocus){ + if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)) updateValue(); + } +} + +void OptionItem::Entering(){ + hasFocus = true; +} + +bool OptionItem::Leaving(){ + hasFocus = false; + return true; +} + +ostream& OptionItem::toString(ostream& out) const{ +return out << "OptionItem ::: displayValue : " << displayValue + << " ; id : " << id + << " ; hasFocus : " << hasFocus + << " ; x,y : " << x << "," << y; +} + +OptionItem::OptionItem( string _id, string _displayValue) { + id = _id; + displayValue = _(_displayValue); + canSelect=true; + hasFocus=false; + width = SCREEN_WIDTH; + height = 20; +} + +//Option Integer + +void OptionInteger::Render(){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + if (hasFocus){ + mFont->SetColor(options[Metrics::OPTION_ITEM_TCH].asColor(ARGB(255,255,255,0))); + }else{ + mFont->SetColor(options[Metrics::OPTION_ITEM_TC].asColor()); + } + JRenderer * renderer = JRenderer::GetInstance(); + renderer->FillRoundRect(x-5,y-2,width-x-5,height,2,options[Metrics::OPTION_ITEM_FC].asColor(ARGB(150,50,50,50))); + mFont->DrawString(displayValue.c_str(),x,y); + char buf[512]; + if (maxValue == 1){ + if (value){ + sprintf(buf, _("Yes").c_str()); + }else{ + sprintf(buf,_("No").c_str()); + } + }else{ + sprintf(buf, "%i", value); + } + mFont->DrawString(buf,width -10 ,y,JGETEXT_RIGHT); +} + +OptionInteger::OptionInteger(string _id, string _displayValue, int _maxValue, int _increment): OptionItem(_id, _displayValue){ + + maxValue = _maxValue; + increment = _increment; + value = ::options[id].number; + hasFocus = false; + x = 0; + y = 0; +} + +void OptionInteger::setData(){ + if(id != "") + options[id] = GameOption(value); +} + + +ostream& OptionInteger::toString(ostream& out) const{ + return out << "OptionItem ::: displayValue : " << displayValue + << " ; id : " << id + << " ; value : " << value + << " ; hasFocus : " << hasFocus + << " ; maxValue : " << maxValue + << " ; increment : " << increment + << " ; x,y : " << x << "," << y; +} + +//Option Select + +void OptionSelect::initSelections(){ + //Find currently active bit in the list. + for(int i=0;iGetJLBFont("graphics/f3"); + if (hasFocus){ + mFont->SetColor(options[Metrics::OPTION_ITEM_TCH].asColor(ARGB(255,255,255,0))); + }else{ + mFont->SetColor(options[Metrics::OPTION_ITEM_TC].asColor()); + } + + JRenderer * renderer = JRenderer::GetInstance(); + renderer->FillRoundRect(x-5,y-2,width-x-5,height,2,options[Metrics::OPTION_ITEM_FC].asColor(ARGB(150,50,50,50))); + mFont->DrawString(displayValue.c_str(),x,y); + + if(value >= 0 && value < selections.size()) + mFont->DrawString(selections[value].c_str(),width-10,y,JGETEXT_RIGHT); + else + mFont->DrawString("Unset",width-10,y,JGETEXT_RIGHT); +} + +void OptionSelect::setData() +{ + if(id == "") return; + if(value >= 0 && value < selections.size()) + options[id] = GameOption(selections[value]); +} + +void OptionSelect::addSelection(string s) +{ + selections.push_back(s); +} + + +ostream& OptionSelect::toString(ostream& out) const +{ + return out << "OptionItem ::: displayValue : " << displayValue + << " ; id : " << id + << " ; value : " << value + << " ; hasFocus : " << hasFocus + << " ; x,y : " << x << "," << y; +} + +//OptionHeader + +void OptionHeader::Render(){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + mFont->SetColor(options[Metrics::OPTION_HEADER_TC].asColor()); + + JRenderer * renderer = JRenderer::GetInstance(); + renderer->FillRoundRect(x-5,y-2,width-x-5,height,2,options[Metrics::OPTION_HEADER_FC].asColor(ARGB(150,80,80,80))); + mFont->DrawString(displayValue.c_str(),width/2,y,JGETEXT_CENTER); +} + +void OptionText::Render(){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + mFont->SetScale(.8); + mFont->SetColor(options[Metrics::OPTION_TEXT_TC].asColor()); + + JRenderer * renderer = JRenderer::GetInstance(); + renderer->FillRoundRect(x-5,y-2,width-x-5,height,2,options[Metrics::OPTION_TEXT_FC].asColor(ARGB(150,80,80,80))); + mFont->DrawString(displayValue.c_str(),x,y,JGETEXT_LEFT); + mFont->SetScale(1); +} + +//OptionProfile + +OptionProfile::~OptionProfile(){ + SAFE_DELETE(mAvatarTex); + SAFE_DELETE(mAvatar); +} + +int OptionProfile::Submode(){ + if(value != initialValue && bCheck){ + bCheck=false; //Just about to check it! + return OPTIONS_SUBMODE_PROFILE; + } + return OPTIONS_SUBMODE_NORMAL; +} + +void OptionProfile::addSelection(string s){ + OptionDirectory::addSelection(s); + + //Check how many options... if 1, we're not selectable. + if(selections.size() > 1) + canSelect = true; + else + canSelect = false; +} + +OptionProfile::OptionProfile(GameApp * _app): OptionDirectory(RESPATH"/profiles",Options::ACTIVE_PROFILE, "Profile"){ + app = _app; + height=100; + addSelection("Default"); + sort(selections.begin(),selections.end()); + initSelections(); + mAvatarTex=NULL; + mAvatar=NULL; + hasFocus=false; + populate(); + bCheck=false; +}; + +void OptionProfile::updateValue(){ + value++; + if (value > selections.size() - 1 || value < 0) + value=0; + + populate(); +} + +void OptionProfile::populate(){ + + JRenderer * renderer = JRenderer::GetInstance(); + string temp = options[Options::ACTIVE_PROFILE].str; + if(value < 0 || value >= selections.size()){ //TODO fail gracefully. + return; + } + + options[Options::ACTIVE_PROFILE].str = selections[value]; + + SAFE_DELETE(mAvatarTex); + mAvatarTex = JRenderer::GetInstance()->LoadTexture(options.profileFile("avatar.jpg","",true,true).c_str(), false); + if (mAvatarTex) { + SAFE_DELETE(mAvatar); + mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50); + renderer->BindTexture(mAvatarTex); //Prevents font corruption. + } + else + mAvatar = NULL; + + options.checkProfile(); + PlayerData * pdata = NEW PlayerData(app->collection); + + options[Options::ACTIVE_PROFILE] = temp; + + char buf[512]; + sprintf(buf,"Credits: %i\nCards: %i",pdata->credits,pdata->collection->totalCards()); + preview = buf; + + + SAFE_DELETE(pdata); +} + +void OptionProfile::Render(){ + JRenderer * renderer = JRenderer::GetInstance(); + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + mFont->SetScale(1); + int spacing = 2+(int)mFont->GetHeight(); + + //Draw faux option. Not highlighted if we've only one. + if (hasFocus && selections.size() > 1){ + mFont->SetColor(options[Metrics::OPTION_ITEM_TCH].asColor(ARGB(255,255,255,0))); + renderer->FillRoundRect(x-5,y-2,width-x-5,20,2,options[Metrics::OPTION_HEADER_FC].asColor(ARGB(150,80,80,80))); + mFont->DrawString("Change Profile",SCREEN_WIDTH/2,y,JGETEXT_CENTER); + }else{ + mFont->SetColor(options[Metrics::OPTION_ITEM_TC].asColor()); + renderer->FillRoundRect(x-5,y-2,width-x-5,20,2,options[Metrics::OPTION_HEADER_FC].asColor(ARGB(150,80,80,80))); + mFont->DrawString("Profile",SCREEN_WIDTH/2,y,JGETEXT_CENTER); + } + + + //Draw preview box. + renderer->FillRoundRect(x-5,y-2+25,width-x-5,height-25,2,options[Metrics::OPTION_ITEM_FC].asColor(ARGB(150,50,50,50))); + + int pX, pY; + pX = x; + pY = y+30; + if(mAvatar){ + renderer->RenderQuad(mAvatar,x,pY); + pX += 40; + } + + mFont->SetColor(options[Metrics::OPTION_TEXT_TC].asColor()); + mFont->DrawString(selections[value].c_str(),pX,pY,JGETEXT_LEFT); + mFont->SetScale(.8); + mFont->DrawString(preview.c_str(),pX,pY+spacing,JGETEXT_LEFT); + mFont->SetScale(1); +} +void OptionProfile::Update(float dt){ + JGE * mEngine = JGE::GetInstance(); + if (hasFocus){ + if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)) updateValue(); + } +} + +void OptionProfile::Entering(){ + JLBFont * menuFont = GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT); + hasFocus = true; + bCheck = false; + initialValue = value; +} +bool OptionProfile::Leaving(){ + + //Choice must be confirmed. + if(value != initialValue){ + bCheck = true; + return false; + } + hasFocus = false; + return true; +} + +void OptionProfile::cancelSubmode() +{ + if(initialValue < 0 || initialValue >= selections.size()) + return; + + options[Options::ACTIVE_PROFILE] = selections[initialValue]; + value = initialValue; + populate(); +} +void OptionProfile::acceptSubmode() +{ + if(value < 0 || value >= selections.size()) + return; + + options[Options::ACTIVE_PROFILE] = selections[value]; + initialValue = value; + populate(); +} + +//OptionDirectory +void OptionDirectory::Reload(){ + DIR *mDip; + struct dirent *mDit; + char buf[4096]; + mDip = opendir(root.c_str()); + + while ((mDit = readdir(mDip))){ + if(mDit->d_name[0] != '.'){ + sprintf(buf,"%s/%s",root.c_str(),mDit->d_name); + std::ifstream file(buf); + if(file){ + file.close(); + continue; + } + if(find(selections.begin(),selections.end(),mDit->d_name) == selections.end()) + addSelection(mDit->d_name); + } + } + + closedir(mDip); + mDip = NULL; + initSelections(); +} + +OptionDirectory::OptionDirectory(string _root, string _id, string _displayValue): OptionSelect(_id, _displayValue){ + DIR *mDip; + struct dirent *mDit; + char buf[4096]; + root = _root; + mDip = opendir(root.c_str()); + + while ((mDit = readdir(mDip))){ + if(mDit->d_name[0] != '.'){ + sprintf(buf,"%s/%s",root.c_str(),mDit->d_name); + std::ifstream file(buf); + if(file){ + file.close(); + continue; + } + addSelection(mDit->d_name); + } + } + + closedir(mDip); + mDip = NULL; + initSelections(); +} + +OptionsList::OptionsList(string name){ + sectionName = name; + failMsg = "NO OPTIONS AVAILABLE"; + nbitems = 0; + current = -1; +} +OptionsList::~OptionsList(){ + for (int i = 0 ; i < nbitems; i++){ + SAFE_DELETE(listItems[i]); + } +} + +void OptionsList::Add(OptionItem * item){ + if (nbitems < MAX_OPTION_ITEMS){ + listItems[nbitems] = item; + nbitems++; + } +} +bool OptionsList::Leaving(){ + if(current >= 0 && current < nbitems) + return listItems[current]->Leaving(); + + return true; +} +void OptionsList::Entering(){ + //Try to force a selectable option. + if(current == -1){ + for (int i = 0 ; i < nbitems; i++){ + if(listItems[i]->canSelect) { + current = i; + listItems[current]->Entering(); + break; + } + } + } + + if(current >= 0 && current < nbitems) + listItems[current]->Entering(); + + return; +} +void OptionsList::Render(){ + JRenderer * renderer = JRenderer::GetInstance(); + + int width = SCREEN_WIDTH; + int listHeight=40; + int listSelectable=0; + int adjustedCurrent=0; + int start = 0, nowPos = 0, vHeight=0; + + + //List is empty. + if (!nbitems && failMsg != ""){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + mFont->SetColor(options[Metrics::MSG_FAIL_TC].asColor(ARGB(255,155,155,155))); + mFont->DrawString(failMsg.c_str(),SCREEN_WIDTH/2, 40, JGETEXT_RIGHT); + return; + } + + //Force a selectable option. + if(current == -1){ + for (int i = 0 ; i < nbitems; i++){ + if(listItems[i]->canSelect) { + current = i; + listItems[current]->Entering(); + break; + } + } + } + //Find out how large our list is. + for (int pos=0;pos < nbitems; pos++){ + listHeight+=listItems[pos]->height+5; + if(listItems[pos]->canSelect){ + listSelectable++; + if(pos < current) adjustedCurrent++; + } + } + + + + //Always fill screen + if(listHeight > SCREEN_HEIGHT) + { + width -= 10; + for (start=current;start > 0; start--) { + vHeight += listItems[start]->height+5; + if(vHeight >= (SCREEN_HEIGHT-60)/2) + break; + } + vHeight = 0; + for (nowPos=nbitems;nowPos > 1; nowPos--) + vHeight += listItems[nowPos-1]->height+5; + + if(vHeight <= SCREEN_HEIGHT-40 && nowPos < start) + start = nowPos; + + } + + vHeight = 0; + nowPos = 40; + + //Render items. + if(start >= 0) + { + for (int pos=0;pos < nbitems; pos++){ + if(pos < start){ + vHeight += listItems[pos]->height + 5; + continue; + } + listItems[pos]->x = 10; + listItems[pos]->y = nowPos; + listItems[pos]->width = width; + nowPos += listItems[pos]->height + 5; + listItems[pos]->Render(); + if(nowPos > SCREEN_HEIGHT) + break; + } + + //Draw scrollbar + if(listHeight > SCREEN_HEIGHT && listSelectable > 1){ + int barPosition = 35+((float)adjustedCurrent/listSelectable)*(SCREEN_HEIGHT-40); + int barLength = (SCREEN_HEIGHT-40) / listSelectable; + if(barLength < 4) barLength = 4; + width = (SCREEN_WIDTH-(width-5))/2; //Find center of blank space by options. + renderer->FillRect(SCREEN_WIDTH-width-1,39,2,SCREEN_HEIGHT-42, + options[Metrics::OPTION_SCROLLBAR_FC].asColor(ARGB(150,150,150,150))); + renderer->FillRoundRect(SCREEN_WIDTH-width-4,barPosition,5,barLength,2, + options[Metrics::OPTION_SCROLLBAR_FCH].asColor(ARGB(255,255,255,255))); + } + } +} + +void OptionsList::save(){ + for (int i = 0; i < nbitems; i++){ + listItems[i]->setData(); + } + ::options.save(); +} + +void OptionsList::Update(float dt){ + JGE * mEngine = JGE::GetInstance(); + int potential = current; + + if (mEngine->GetButtonClick(PSP_CTRL_UP)) + { + if (potential > 0){ + potential--; + while(potential > 0 && listItems[potential]->canSelect == false) + potential--; + if(potential < 0 || !listItems[potential]->canSelect) + potential = -1; + else if(listItems[current]->Leaving()){ + current = potential; + listItems[current]->Entering(); + } + } + } + else if (mEngine->GetButtonClick(PSP_CTRL_DOWN)) + { + if (potential < nbitems-1){ + potential++; + while(potential < nbitems-1 && listItems[potential]->canSelect == false) + potential++; + if(potential == nbitems || !listItems[potential]->canSelect) + potential = -1; + else if(potential != current && listItems[current]->Leaving()){ + current = potential; + listItems[current]->Entering(); + } + } + } + for (int i = 0 ; i < nbitems; i++){ + listItems[i]->Update(dt); + } +} + + +void OptionsMenu::Add(OptionsList * tab){ + if (nbitems < MAX_OPTION_TABS){ + tabs[nbitems] = tab; + nbitems++; + if (current < 0){ + current = 0; + } + + } +} + +void OptionsMenu::Render(){ + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + + if (!nbitems){ + mFont->DrawString("NO OPTIONS AVAILABLE",SCREEN_WIDTH/2, 5, JGETEXT_RIGHT); + return; + } + + JRenderer * renderer = JRenderer::GetInstance(); + + int offset = 0; + for(int i=0;iGetStringWidth(tabs[i]->sectionName.c_str()); + if(i == current){ + mFont->SetColor(options[Metrics::OPTION_TAB_TCH].asColor()); + renderer->FillRoundRect(offset+5,5,w + 5,25,2,options[Metrics::OPTION_TAB_FCH].asColor(ARGB(150,150,150,150))); + } + else{ + mFont->SetColor(options[Metrics::OPTION_TAB_TC].asColor(ARGB(255,155,155,155))); + renderer->FillRoundRect(offset+5,5,w + 5,25,2,options[Metrics::OPTION_TAB_FC].asColor(ARGB(150,50,50,50))); + } + mFont->DrawString(tabs[i]->sectionName.c_str(),offset+10,10); + offset += w + 10 + 2; + } + + if(current > -1 && current < nbitems && tabs[current]) + tabs[current]->Render(); +} + +void OptionsMenu::Update(float dt){ + JGE * mEngine = JGE::GetInstance(); + if(current < 0 || current >= nbitems) + return; + + //We use the shoulder buttons to switch tabs, if we've got them. + if (mEngine->GetButtonClick(PSP_CTRL_LTRIGGER)) + { + if (current > 0) + { + if(tabs[current]->Leaving()){ + current--; + tabs[current]->Entering(); + } + } + } + else if (mEngine->GetButtonClick(PSP_CTRL_RTRIGGER)) + { + if (current < nbitems -1) + { + if(tabs[current]->Leaving()){ + current++; + tabs[current]->Entering(); + } + } + } + + tabs[current]->Update(dt); +} + +OptionsMenu::OptionsMenu(){ + nbitems=0; + current=0; + for(int x=0;xsave(); +} + +bool OptionsMenu::isTab(string name){ + if(current <0 || current >= nbitems) + return false; + else if(tabs[current]->sectionName == name) + return true; + + return false; +}; + +int OptionsMenu::Submode() +{ + if(current <0 || current >= nbitems) + return OPTIONS_SUBMODE_NORMAL; + + return tabs[current]->Submode(); +} + +void OptionsMenu::acceptSubmode() +{ + if(current > -1 && current < nbitems) + tabs[current]->acceptSubmode(); +} +void OptionsMenu::reloadValues() +{ + if(current > -1 && current < nbitems) + tabs[current]->reloadValues(); +} + +void OptionsMenu::cancelSubmode() +{ + if(current > -1 && current < nbitems) + tabs[current]->cancelSubmode(); +} + + +int OptionsList::Submode() +{ + if(current <0 || current >= nbitems) + return OPTIONS_SUBMODE_NORMAL; + + return listItems[current]->Submode(); +} + +void OptionsList::reloadValues() +{ + for(int i=0;iReload(); + } +} +void OptionsList::acceptSubmode() +{ + if(current > -1 && current < nbitems) + listItems[current]->acceptSubmode(); +} + +void OptionsList::cancelSubmode() +{ + if(current > -1 && current < nbitems) + listItems[current]->cancelSubmode(); +} + +//OptionString + +void OptionString::Render(){ + + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + if (hasFocus){ + mFont->SetColor(options[Metrics::OPTION_ITEM_TCH].asColor(ARGB(255,255,255,0))); + }else{ + mFont->SetColor(options[Metrics::OPTION_ITEM_TC].asColor()); + } + JRenderer * renderer = JRenderer::GetInstance(); + renderer->FillRoundRect(x-5,y-2,width-x-5,height,2,options[Metrics::OPTION_ITEM_FC].asColor(ARGB(150,50,50,50))); + + if(!bShowValue){ + mFont->DrawString(displayValue.c_str(),(x+width)/2,y,JGETEXT_CENTER); + } + else{ + mFont->DrawString(displayValue.c_str(),x,y); + int w = mFont->GetStringWidth(value.c_str()-10); + mFont->DrawString(value.c_str(),width - w,y,JGETEXT_RIGHT); + } +} + +void OptionString::setData(){ + if(id != "") + options[id] = GameOption(value); +} +void OptionString::updateValue(){ + options.keypadStart(value,&value); + options.keypadTitle(displayValue); +} + +void OptionNewProfile::updateValue(){ + options.keypadStart("",&value); + options.keypadTitle(displayValue); +} + +void OptionNewProfile::Update(float dt){ + if(value != ""){ + string temp; + temp = options[Options::ACTIVE_PROFILE].str; + value = options.keypadFinish(); + if(value == "") + return; + + if(temp != value){ + options[Options::ACTIVE_PROFILE] = value; + options.checkProfile(); + } + value = ""; + bChanged = true; + } + OptionItem::Update(dt); +} + +int OptionNewProfile::Submode(){ + if(bChanged){ + bChanged=false; //Just about to check it! + return OPTIONS_SUBMODE_RELOAD; + } + return OPTIONS_SUBMODE_NORMAL; +} +OptionString::OptionString(string _id, string _displayValue): OptionItem(_id, _displayValue) +{ + bShowValue=true; + if(_id != "") + value=options[_id].str; +}; + +ostream& OptionString::toString(ostream& out) const{ +return out << "OptionString ::: displayValue : " << displayValue + << " ; id : " << id + << " ; value : " << value + << " ; hasFocus : " << hasFocus + << " ; x,y : " << x << "," << y; +} \ No newline at end of file diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index 194ed9f35..ab024cd8e 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -59,7 +59,7 @@ Player * Player::opponent(){ } HumanPlayer::HumanPlayer(MTGPlayerCards * deck, string file, string fileSmall) : Player(deck, file, fileSmall) { - mAvatarTex = JRenderer::GetInstance()->LoadTexture("player/avatar.jpg", TEX_TYPE_USE_VRAM); + mAvatarTex = JRenderer::GetInstance()->LoadTexture(options.profileFile("avatar.jpg","player",true,true).c_str(), TEX_TYPE_USE_VRAM); if (mAvatarTex) mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50); } diff --git a/projects/mtg/src/PlayerData.cpp b/projects/mtg/src/PlayerData.cpp index a4b9f8819..365bab163 100644 --- a/projects/mtg/src/PlayerData.cpp +++ b/projects/mtg/src/PlayerData.cpp @@ -1,4 +1,5 @@ #include "../include/config.h" +#include "../include/GameOptions.h" #include "../include/PlayerData.h" #include @@ -7,7 +8,8 @@ PlayerData::PlayerData(MTGAllCards * allcards){ //CREDITS credits = 3000; //Default value - std::ifstream file(PLAYER_SAVEFILE); + + std::ifstream file(options.profileFile(PLAYER_SAVEFILE,"",false).c_str()); std::string s; if(file){ if(std::getline(file,s)){ @@ -19,12 +21,12 @@ PlayerData::PlayerData(MTGAllCards * allcards){ } //COLLECTION - collection = NEW MTGDeck(RESPATH"/player/collection.dat", allcards->mCache , allcards); + collection = NEW MTGDeck(options.profileFile(PLAYER_COLLECTION,"",false).c_str(), allcards->mCache, allcards); } int PlayerData::save(){ - std::ofstream file(PLAYER_SAVEFILE); + std::ofstream file(options.profileFile(PLAYER_SAVEFILE,"",false).c_str()); char writer[64]; if (file){ sprintf(writer,"%i\n", credits); diff --git a/projects/mtg/src/ShopItem.cpp b/projects/mtg/src/ShopItem.cpp index 7d036742e..f8f002d8f 100644 --- a/projects/mtg/src/ShopItem.cpp +++ b/projects/mtg/src/ShopItem.cpp @@ -1,13 +1,13 @@ -#include "../include/config.h" -#include "../include/ShopItem.h" -#include "../include/GameStateShop.h" -#include "../include/CardGui.h" -#include "../include/TexturesCache.h" -#include "../include/Translate.h" -#include - - - +#include "../include/config.h" +#include "../include/ShopItem.h" +#include "../include/GameStateShop.h" +#include "../include/CardGui.h" +#include "../include/TexturesCache.h" +#include "../include/Translate.h" +#include + + + float ShopItems::_x1[] = { 79, 20, 27,103,154,187,102,145,199,133,183}; float ShopItems::_y1[] = {150,193,222,167,164,156,195,190,176,220,220}; @@ -18,417 +18,417 @@ float ShopItems::_y3[] = {163,202,255,183,180,170,219,212,195,250,251}; float ShopItems::_x4[] = { 74, 88, 64,131,171,221,123,187,225,141,237}; - float ShopItems::_y4[] = {167,187,248,182,182,168,219,208,196,258,245}; - - -ShopItem::ShopItem(int id, JLBFont *font, char* text, JQuad * _quad,JQuad * _thumb, float _xy[], bool hasFocus, int _price): JGuiObject(id), mFont(font), mText(text), quad(_quad), thumb(_thumb), price(_price) -{ - for (int i = 0; i < 8; ++i){ - xy[i] = _xy[i]; - } - quantity = 10; - card = NULL; - mHasFocus = hasFocus; - - mScale = 1.0f; - mTargetScale = 1.0f; - - mesh=NEW hgeDistortionMesh(2,2); - mesh->SetTexture(thumb->mTex); - float x0,y0,w0,h0; - thumb->GetTextureRect(&x0,&y0,&w0,&h0); - mesh->SetTextureRect(x0,y0,w0,h0); - mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); - mesh->SetDisplacement(0, 0, xy[0],xy[1], HGEDISP_NODE); - mesh->SetDisplacement(1, 0, xy[2] - w0,xy[3], HGEDISP_NODE); - mesh->SetDisplacement(0, 1,xy[4],xy[5]-h0, HGEDISP_NODE); - mesh->SetDisplacement(1, 1, xy[6]-w0,xy[7]-h0, HGEDISP_NODE); - mesh->SetColor(1,1,ARGB(255,100,100,100)); - mesh->SetColor(0,1,ARGB(255,100,100,100)); - mesh->SetColor(1,0,ARGB(255,100,100,100)); - mesh->SetColor(0,0,ARGB(255,200,200,200)); - if (hasFocus) - Entering(); -} - -ShopItem::ShopItem(int id, JLBFont *font, int _cardid, float _xy[], bool hasFocus, MTGAllCards * collection, int _price, DeckDataWrapper * ddw): JGuiObject(id), mFont(font), price(_price){ - for (int i = 0; i < 8; ++i){ - xy[i] = _xy[i]; - } - mHasFocus = hasFocus; - mScale = 1.0f; - mTargetScale = 1.0f; - - if (hasFocus) - Entering(); - - card = collection->getCardById(_cardid); - updateCount(ddw); - - quantity = 1 + (rand() % 4); - if (card->getRarity() == Constants::RARITY_L) quantity = 50; - quad = NULL; - - thumb = cache.getThumb(card); - - if (!thumb){ - switch(card->getColor()) - { - case Constants::MTG_COLOR_GREEN: thumb = GameApp::CommonRes->GetQuad("green_thumb"); break; - case Constants::MTG_COLOR_BLUE : thumb = GameApp::CommonRes->GetQuad("blue_thumb"); break; - case Constants::MTG_COLOR_RED : thumb = GameApp::CommonRes->GetQuad("red_thumb"); break; - case Constants::MTG_COLOR_BLACK: thumb = GameApp::CommonRes->GetQuad("black_thumb"); break; - case Constants::MTG_COLOR_WHITE: thumb = GameApp::CommonRes->GetQuad("white_thumb"); break; - default: thumb = GameApp::CommonRes->GetQuad("black_thumb"); break; - } - } - if (thumb){ - mesh=NEW hgeDistortionMesh(2,2); - mesh->SetTexture(thumb->mTex); - float x0,y0,w0,h0; - thumb->GetTextureRect(&x0,&y0,&w0,&h0); - mesh->SetTextureRect(x0,y0,w0,h0); - mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); - mesh->SetDisplacement(0, 0, xy[0],xy[1], HGEDISP_NODE); - mesh->SetDisplacement(1, 0, xy[2] - w0,xy[3], HGEDISP_NODE); - mesh->SetDisplacement(0, 1,xy[4],xy[5]-h0, HGEDISP_NODE); - mesh->SetDisplacement(1, 1, xy[6]-w0,xy[7]-h0, HGEDISP_NODE); - mesh->SetColor(1,1,ARGB(255,100,100,100)); - mesh->SetColor(0,1,ARGB(255,100,100,100)); - mesh->SetColor(1,0,ARGB(255,100,100,100)); - mesh->SetColor(0,0,ARGB(255,200,200,200)); - }else{ - mesh = NULL; - } -} - - -int ShopItem::updateCount(DeckDataWrapper * ddw){ - if (!card) return 0; - nameCount = ddw->countByName(card); - return nameCount; -} - -ShopItem::~ShopItem(){ - OutputDebugString("delete shopitem\n"); - SAFE_DELETE(mesh); -} - -const char * ShopItem::getText(){ - return mText.c_str(); -} - - -void ShopItem::Render(){ - if (mHasFocus){ - mFont->SetColor(ARGB(255,255,255,0)); - }else{ - mFont->SetColor(ARGB(255,255,255,255)); - } - if (!quantity){ - mFont->SetColor(ARGB(255,128,128,128)); - } - - if (card){ - if (nameCount){ - char buffer[512]; - sprintf(buffer, "%s (%i)", _(card->name).c_str(), nameCount ); - mText = buffer; - }else{ - mText = _(card->name).c_str(); - } - } - - JRenderer * renderer = JRenderer::GetInstance(); - //float x0 = mX; - //float y0 = mY - (mScale > 1 ? 4 : 0); - /* if (GetId()%2){ - float xs[] = {mX, mX, mX+230,mX+230}; - float ys[] = {mY-5+17,mY-5+19,mY-5+35,mY-5} ; - - renderer->FillPolygon(xs,ys,4,ARGB(200,0,0,0)); - x0 = mX + 230 -30; - mFont->DrawString(mText.c_str(), x0, mY + 8,JGETEXT_RIGHT); - - }else{ - float xs[] = {mX-5, mX-5, mX-5+230,mX-5+230,}; - float ys[] = {mY-5,mY-5+35,mY-5+17,mY-5+19} ; - renderer->FillPolygon(xs,ys,4,ARGB(128,0,0,0)); - mFont->DrawString(mText.c_str(), mX + 30, mY + 8); - }*/ - //renderer->FillRect(mX-5, mY-5,230,35, ); - - - if (mesh){ - mesh->Render(0,0); - //renderer->RenderQuad(thumb,x0,y0,0,mScale * 0.45,mScale * 0.45); - }else{ - //NOTHING - } - if (mHasFocus){ - if (card) quad = cache.getQuad(card); - if (quad){ - quad->SetColor(ARGB(255,255,255,255)); - renderer->RenderQuad(quad,SCREEN_WIDTH - 105,SCREEN_HEIGHT/2 - 5,0, 0.9f,0.9f); - }else{ - if (card) CardGui::alternateRender(card,Pos(SCREEN_WIDTH - 105,SCREEN_HEIGHT/2 - 5,0.9f* 285/250, 0,255)); - - } - mFont->DrawString(mText.c_str(), SCREEN_WIDTH/2 - 50, SCREEN_HEIGHT - 16,JGETEXT_CENTER); - } -} - - - - -void ShopItem::Update(float dt) -{ - if (mScale < mTargetScale){ - mScale += 8.0f*dt; - if (mScale > mTargetScale) - mScale = mTargetScale; - }else if (mScale > mTargetScale){ - mScale -= 8.0f*dt; - if (mScale < mTargetScale) - mScale = mTargetScale; - } -} - - - - -void ShopItem::Entering() -{ - for (int i = 0; i < 2; ++i){ - for (int j = 0; j < 2; ++j){ - mesh->SetColor(i,j,ARGB(255,255,255,255)); - } - } - - - mHasFocus = true; - mTargetScale = 1.2f; -} - - -bool ShopItem::Leaving(u32 key) -{ - mesh->SetColor(1,1,ARGB(255,100,100,100)); - mesh->SetColor(0,1,ARGB(255,100,100,100)); - mesh->SetColor(1,0,ARGB(255,100,100,100)); - mesh->SetColor(0,0,ARGB(255,200,200,200)); - - mHasFocus = false; - mTargetScale = 1.0f; - return true; -} - - -bool ShopItem::ButtonPressed() -{ - return (quantity >0); -} - - -ShopItems::ShopItems(int id, JGuiListener* listener, JLBFont* font, int x, int y, MTGAllCards * _collection, int _setIds[]): JGuiController(id, listener), mX(x), mY(y), mFont(font), collection(_collection){ - mHeight = 0; - showPriceDialog = -1; - dialog = NULL; - pricelist = NEW PriceList(RESPATH"/settings/prices.dat",_collection); - playerdata = NEW PlayerData(_collection); - display = NULL; - for (int i=0; i < SHOP_BOOSTERS; i++){ - setIds[i] = _setIds[i]; - }; - myCollection = NEW DeckDataWrapper(NEW MTGDeck(RESPATH"/player/collection.dat", NULL,_collection)); -} - - - -void ShopItems::Add(int cardid){ - int rnd = (rand() % 20); - int price = pricelist->getPrice(cardid); - price = price + price * (rnd -10)/100; - float xy[] = {_x1[mCount],_y1[mCount],_x2[mCount],_y2[mCount],_x3[mCount],_y3[mCount],_x4[mCount],_y4[mCount]}; - JGuiController::Add(NEW ShopItem(mCount, mFont, cardid, xy, (mCount == 0),collection, price,myCollection)); - mHeight += 22; -} - -void ShopItems::Add(char * text, JQuad * quad,JQuad * thumb, int price){ - float xy[] = {_x1[mCount],_y1[mCount],_x2[mCount],_y2[mCount],_x3[mCount],_y3[mCount],_x4[mCount],_y4[mCount]}; - JGuiController::Add(NEW ShopItem(mCount, mFont, text, quad, thumb, xy, (mCount == 0), price)); - mHeight += 22; -} - -void ShopItems::Update(float dt){ - if (display){ - while (u32 key = JGE::GetInstance()->ReadButton()) display->CheckUserInput(key); - if (display) display->Update(dt); - }else{ - if (showPriceDialog!=-1){ - ShopItem * item = ((ShopItem *)mObjects[showPriceDialog]); - int price = item->price; - char buffer[4096]; - sprintf(buffer,"%s : %i credits",item->getText(),price); - if(!dialog){ - dialog = NEW SimpleMenu(1,this,GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT),SCREEN_WIDTH-300,SCREEN_HEIGHT/2,buffer); - dialog->Add(1,"Yes"); - dialog->Add(2,"No"); - } - else{ - dialog->Update(dt); - } - }else{ - u32 buttons[] = {PSP_CTRL_LEFT,PSP_CTRL_DOWN,PSP_CTRL_RIGHT,PSP_CTRL_UP,PSP_CTRL_SQUARE}; - for (int i = 0; i < 5; ++i){ - if (JGE::GetInstance()->GetButtonClick(buttons[i])){ - showList = 500; - } - } - SAFE_DELETE(dialog); - JGuiController::Update(dt); - } - - } - -} - - -void ShopItems::Render(){ - JGuiController::Render(); - if (showPriceDialog==-1){ - - }else{ - if(dialog){ - dialog->Render(); - } - } - char credits[512]; - sprintf(credits,_("credits: %i").c_str(), playerdata->credits); - unsigned int len = 4 + mFont->GetStringWidth(credits); - mFont->SetColor(ARGB(200,0,0,0)); - mFont->DrawString(credits, 5, SCREEN_HEIGHT - 13); - mFont->SetColor(ARGB(255,255,255,255)); - mFont->DrawString(credits, 5, SCREEN_HEIGHT - 15); - if (display) display->Render(); -} - -void ShopItems::pricedialog(int id, int mode){ - if (mode){ - showPriceDialog = id; - }else{ - showPriceDialog = -1; - } -} - -void ShopItems::ButtonPressed(int controllerId, int controlId){ - if (controllerId == 12){ - safeDeleteDisplay(); - return; - } - - ShopItem * item = ((ShopItem *)mObjects[showPriceDialog]); - int price = item->price; - switch(controlId){ - case 1: - if (playerdata->credits >= price){ - playerdata->credits -= price; - if (item->card){ - int rnd = (rand() % 25); - price = price + (rnd * price)/100; - pricelist->setPrice(item->card->getMTGId(),price); - playerdata->collection->add(item->card); - item->quantity--; - myCollection->Add(item->card); - item->nameCount++; - item->price = price; - }else{ - safeDeleteDisplay(); - display = NEW CardDisplay(12,NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT/2,this,NULL,5); - - MTGDeck * tempDeck = NEW MTGDeck(NULL,playerdata->collection->database); - int rare_or_mythic = Constants::RARITY_R; - int rnd = rand() % 8; - if (rnd == 0) rare_or_mythic = Constants::RARITY_M; - int sets[] = {setIds[showPriceDialog]}; - - tempDeck->addRandomCards(1, sets,1,rare_or_mythic); - tempDeck->addRandomCards(3, sets,1,Constants::RARITY_U); - tempDeck->addRandomCards(11, sets,1,Constants::RARITY_C); - - playerdata->collection->add(tempDeck); - myCollection->Add(tempDeck); - - for (int j = 0; j < mCount; j++){ - ShopItem * si = ((ShopItem *)mObjects[j]); - si->updateCount(myCollection); - } - - int i = 0; - for (map::iterator it = tempDeck->cards.begin(); it!=tempDeck->cards.end(); it++){ - MTGCard * c = tempDeck->getCardById(it->first); - for (int j = 0; j < it->second; j++){ - MTGCardInstance * card = NEW MTGCardInstance(c, NULL); - displayCards[i] = card; - display->AddCard(card); - i++; - } - } - delete tempDeck; - } - showPriceDialog = -1; - }else{ - //error not enough money - } - break; - case 2: - if (item->card){ - int rnd = (rand() % 25); - price = price - (rnd * price)/100; - pricelist->setPrice(item->card->getMTGId(),price); - } - showPriceDialog = -1; - break; - } -} - - -void ShopItems::safeDeleteDisplay(){ - if (!display) return; - for (int i = 0; i < display->mCount; i++){ - delete displayCards[i]; - } - SAFE_DELETE(display); -} - -void ShopItems::saveAll(){ - savePriceList(); - playerdata->save(); -} - -void ShopItems::savePriceList(){ - pricelist->save(); -} - -ShopItems::~ShopItems(){ - SAFE_DELETE(pricelist); - SAFE_DELETE(playerdata); - SAFE_DELETE(dialog); - safeDeleteDisplay(); - SAFE_DELETE(myCollection); -} - -ostream& ShopItem::toString(ostream& out) const -{ - return out << "ShopItem ::: mHasFocus : " << mHasFocus - << " ; mFont : " << mFont - << " ; mText : " << mText - << " ; quad : " << quad - << " ; thumb : " << thumb - << " ; mScale : " << mScale - << " ; mTargetScale : " << mTargetScale - << " ; nameCount : " << nameCount - << " ; quantity : " << quantity - << " ; card : " << card - << " ; price : " << price; -} + float ShopItems::_y4[] = {167,187,248,182,182,168,219,208,196,258,245}; + + +ShopItem::ShopItem(int id, JLBFont *font, char* text, JQuad * _quad,JQuad * _thumb, float _xy[], bool hasFocus, int _price): JGuiObject(id), mFont(font), mText(text), quad(_quad), thumb(_thumb), price(_price) +{ + for (int i = 0; i < 8; ++i){ + xy[i] = _xy[i]; + } + quantity = 10; + card = NULL; + mHasFocus = hasFocus; + + mScale = 1.0f; + mTargetScale = 1.0f; + + mesh=NEW hgeDistortionMesh(2,2); + mesh->SetTexture(thumb->mTex); + float x0,y0,w0,h0; + thumb->GetTextureRect(&x0,&y0,&w0,&h0); + mesh->SetTextureRect(x0,y0,w0,h0); + mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); + mesh->SetDisplacement(0, 0, xy[0],xy[1], HGEDISP_NODE); + mesh->SetDisplacement(1, 0, xy[2] - w0,xy[3], HGEDISP_NODE); + mesh->SetDisplacement(0, 1,xy[4],xy[5]-h0, HGEDISP_NODE); + mesh->SetDisplacement(1, 1, xy[6]-w0,xy[7]-h0, HGEDISP_NODE); + mesh->SetColor(1,1,ARGB(255,100,100,100)); + mesh->SetColor(0,1,ARGB(255,100,100,100)); + mesh->SetColor(1,0,ARGB(255,100,100,100)); + mesh->SetColor(0,0,ARGB(255,200,200,200)); + if (hasFocus) + Entering(); +} + +ShopItem::ShopItem(int id, JLBFont *font, int _cardid, float _xy[], bool hasFocus, MTGAllCards * collection, int _price, DeckDataWrapper * ddw): JGuiObject(id), mFont(font), price(_price){ + for (int i = 0; i < 8; ++i){ + xy[i] = _xy[i]; + } + mHasFocus = hasFocus; + mScale = 1.0f; + mTargetScale = 1.0f; + + if (hasFocus) + Entering(); + + card = collection->getCardById(_cardid); + updateCount(ddw); + + quantity = 1 + (rand() % 4); + if (card->getRarity() == Constants::RARITY_L) quantity = 50; + quad = NULL; + + thumb = cache.getThumb(card); + + if (!thumb){ + switch(card->getColor()) + { + case Constants::MTG_COLOR_GREEN: thumb = GameApp::CommonRes->GetQuad("green_thumb"); break; + case Constants::MTG_COLOR_BLUE : thumb = GameApp::CommonRes->GetQuad("blue_thumb"); break; + case Constants::MTG_COLOR_RED : thumb = GameApp::CommonRes->GetQuad("red_thumb"); break; + case Constants::MTG_COLOR_BLACK: thumb = GameApp::CommonRes->GetQuad("black_thumb"); break; + case Constants::MTG_COLOR_WHITE: thumb = GameApp::CommonRes->GetQuad("white_thumb"); break; + default: thumb = GameApp::CommonRes->GetQuad("black_thumb"); break; + } + } + if (thumb){ + mesh=NEW hgeDistortionMesh(2,2); + mesh->SetTexture(thumb->mTex); + float x0,y0,w0,h0; + thumb->GetTextureRect(&x0,&y0,&w0,&h0); + mesh->SetTextureRect(x0,y0,w0,h0); + mesh->Clear(ARGB(0xFF,0xFF,0xFF,0xFF)); + mesh->SetDisplacement(0, 0, xy[0],xy[1], HGEDISP_NODE); + mesh->SetDisplacement(1, 0, xy[2] - w0,xy[3], HGEDISP_NODE); + mesh->SetDisplacement(0, 1,xy[4],xy[5]-h0, HGEDISP_NODE); + mesh->SetDisplacement(1, 1, xy[6]-w0,xy[7]-h0, HGEDISP_NODE); + mesh->SetColor(1,1,ARGB(255,100,100,100)); + mesh->SetColor(0,1,ARGB(255,100,100,100)); + mesh->SetColor(1,0,ARGB(255,100,100,100)); + mesh->SetColor(0,0,ARGB(255,200,200,200)); + }else{ + mesh = NULL; + } +} + + +int ShopItem::updateCount(DeckDataWrapper * ddw){ + if (!card) return 0; + nameCount = ddw->countByName(card); + return nameCount; +} + +ShopItem::~ShopItem(){ + OutputDebugString("delete shopitem\n"); + SAFE_DELETE(mesh); +} + +const char * ShopItem::getText(){ + return mText.c_str(); +} + + +void ShopItem::Render(){ + if (mHasFocus){ + mFont->SetColor(ARGB(255,255,255,0)); + }else{ + mFont->SetColor(ARGB(255,255,255,255)); + } + if (!quantity){ + mFont->SetColor(ARGB(255,128,128,128)); + } + + if (card){ + if (nameCount){ + char buffer[512]; + sprintf(buffer, "%s (%i)", _(card->name).c_str(), nameCount ); + mText = buffer; + }else{ + mText = _(card->name).c_str(); + } + } + + JRenderer * renderer = JRenderer::GetInstance(); + //float x0 = mX; + //float y0 = mY - (mScale > 1 ? 4 : 0); + /* if (GetId()%2){ + float xs[] = {mX, mX, mX+230,mX+230}; + float ys[] = {mY-5+17,mY-5+19,mY-5+35,mY-5} ; + + renderer->FillPolygon(xs,ys,4,ARGB(200,0,0,0)); + x0 = mX + 230 -30; + mFont->DrawString(mText.c_str(), x0, mY + 8,JGETEXT_RIGHT); + + }else{ + float xs[] = {mX-5, mX-5, mX-5+230,mX-5+230,}; + float ys[] = {mY-5,mY-5+35,mY-5+17,mY-5+19} ; + renderer->FillPolygon(xs,ys,4,ARGB(128,0,0,0)); + mFont->DrawString(mText.c_str(), mX + 30, mY + 8); + }*/ + //renderer->FillRect(mX-5, mY-5,230,35, ); + + + if (mesh){ + mesh->Render(0,0); + //renderer->RenderQuad(thumb,x0,y0,0,mScale * 0.45,mScale * 0.45); + }else{ + //NOTHING + } + if (mHasFocus){ + if (card) quad = cache.getQuad(card); + if (quad){ + quad->SetColor(ARGB(255,255,255,255)); + renderer->RenderQuad(quad,SCREEN_WIDTH - 105,SCREEN_HEIGHT/2 - 5,0, 0.9f,0.9f); + }else{ + if (card) CardGui::alternateRender(card,Pos(SCREEN_WIDTH - 105,SCREEN_HEIGHT/2 - 5,0.9f* 285/250, 0,255)); + + } + mFont->DrawString(mText.c_str(), SCREEN_WIDTH/2 - 50, SCREEN_HEIGHT - 16,JGETEXT_CENTER); + } +} + + + + +void ShopItem::Update(float dt) +{ + if (mScale < mTargetScale){ + mScale += 8.0f*dt; + if (mScale > mTargetScale) + mScale = mTargetScale; + }else if (mScale > mTargetScale){ + mScale -= 8.0f*dt; + if (mScale < mTargetScale) + mScale = mTargetScale; + } +} + + + + +void ShopItem::Entering() +{ + for (int i = 0; i < 2; ++i){ + for (int j = 0; j < 2; ++j){ + mesh->SetColor(i,j,ARGB(255,255,255,255)); + } + } + + + mHasFocus = true; + mTargetScale = 1.2f; +} + + +bool ShopItem::Leaving(u32 key) +{ + mesh->SetColor(1,1,ARGB(255,100,100,100)); + mesh->SetColor(0,1,ARGB(255,100,100,100)); + mesh->SetColor(1,0,ARGB(255,100,100,100)); + mesh->SetColor(0,0,ARGB(255,200,200,200)); + + mHasFocus = false; + mTargetScale = 1.0f; + return true; +} + + +bool ShopItem::ButtonPressed() +{ + return (quantity >0); +} + + +ShopItems::ShopItems(int id, JGuiListener* listener, JLBFont* font, int x, int y, MTGAllCards * _collection, int _setIds[]): JGuiController(id, listener), mX(x), mY(y), mFont(font), collection(_collection){ + mHeight = 0; + showPriceDialog = -1; + dialog = NULL; + pricelist = NEW PriceList(RESPATH"/settings/prices.dat",_collection); + playerdata = NEW PlayerData(_collection); + display = NULL; + for (int i=0; i < SHOP_BOOSTERS; i++){ + setIds[i] = _setIds[i]; + }; + myCollection = NEW DeckDataWrapper(NEW MTGDeck(options.profileFile(PLAYER_COLLECTION).c_str(), NULL,_collection)); +} + + + +void ShopItems::Add(int cardid){ + int rnd = (rand() % 20); + int price = pricelist->getPrice(cardid); + price = price + price * (rnd -10)/100; + float xy[] = {_x1[mCount],_y1[mCount],_x2[mCount],_y2[mCount],_x3[mCount],_y3[mCount],_x4[mCount],_y4[mCount]}; + JGuiController::Add(NEW ShopItem(mCount, mFont, cardid, xy, (mCount == 0),collection, price,myCollection)); + mHeight += 22; +} + +void ShopItems::Add(char * text, JQuad * quad,JQuad * thumb, int price){ + float xy[] = {_x1[mCount],_y1[mCount],_x2[mCount],_y2[mCount],_x3[mCount],_y3[mCount],_x4[mCount],_y4[mCount]}; + JGuiController::Add(NEW ShopItem(mCount, mFont, text, quad, thumb, xy, (mCount == 0), price)); + mHeight += 22; +} + +void ShopItems::Update(float dt){ + if (display){ + while (u32 key = JGE::GetInstance()->ReadButton()) display->CheckUserInput(key); + if (display) display->Update(dt); + }else{ + if (showPriceDialog!=-1){ + ShopItem * item = ((ShopItem *)mObjects[showPriceDialog]); + int price = item->price; + char buffer[4096]; + sprintf(buffer,"%s : %i credits",item->getText(),price); + if(!dialog){ + dialog = NEW SimpleMenu(1,this,GameApp::CommonRes->GetJLBFont(Constants::MENU_FONT),SCREEN_WIDTH-300,SCREEN_HEIGHT/2,buffer); + dialog->Add(1,"Yes"); + dialog->Add(2,"No"); + } + else{ + dialog->Update(dt); + } + }else{ + u32 buttons[] = {PSP_CTRL_LEFT,PSP_CTRL_DOWN,PSP_CTRL_RIGHT,PSP_CTRL_UP,PSP_CTRL_SQUARE}; + for (int i = 0; i < 5; ++i){ + if (JGE::GetInstance()->GetButtonClick(buttons[i])){ + showList = 500; + } + } + SAFE_DELETE(dialog); + JGuiController::Update(dt); + } + + } + +} + + +void ShopItems::Render(){ + JGuiController::Render(); + if (showPriceDialog==-1){ + + }else{ + if(dialog){ + dialog->Render(); + } + } + char credits[512]; + sprintf(credits,_("credits: %i").c_str(), playerdata->credits); + unsigned int len = 4 + mFont->GetStringWidth(credits); + mFont->SetColor(ARGB(200,0,0,0)); + mFont->DrawString(credits, 5, SCREEN_HEIGHT - 13); + mFont->SetColor(ARGB(255,255,255,255)); + mFont->DrawString(credits, 5, SCREEN_HEIGHT - 15); + if (display) display->Render(); +} + +void ShopItems::pricedialog(int id, int mode){ + if (mode){ + showPriceDialog = id; + }else{ + showPriceDialog = -1; + } +} + +void ShopItems::ButtonPressed(int controllerId, int controlId){ + if (controllerId == 12){ + safeDeleteDisplay(); + return; + } + + ShopItem * item = ((ShopItem *)mObjects[showPriceDialog]); + int price = item->price; + switch(controlId){ + case 1: + if (playerdata->credits >= price){ + playerdata->credits -= price; + if (item->card){ + int rnd = (rand() % 25); + price = price + (rnd * price)/100; + pricelist->setPrice(item->card->getMTGId(),price); + playerdata->collection->add(item->card); + item->quantity--; + myCollection->Add(item->card); + item->nameCount++; + item->price = price; + }else{ + safeDeleteDisplay(); + display = NEW CardDisplay(12,NULL, SCREEN_WIDTH - 200, SCREEN_HEIGHT/2,this,NULL,5); + + MTGDeck * tempDeck = NEW MTGDeck(NULL,playerdata->collection->database); + int rare_or_mythic = Constants::RARITY_R; + int rnd = rand() % 8; + if (rnd == 0) rare_or_mythic = Constants::RARITY_M; + int sets[] = {setIds[showPriceDialog]}; + + tempDeck->addRandomCards(1, sets,1,rare_or_mythic); + tempDeck->addRandomCards(3, sets,1,Constants::RARITY_U); + tempDeck->addRandomCards(11, sets,1,Constants::RARITY_C); + + playerdata->collection->add(tempDeck); + myCollection->Add(tempDeck); + + for (int j = 0; j < mCount; j++){ + ShopItem * si = ((ShopItem *)mObjects[j]); + si->updateCount(myCollection); + } + + int i = 0; + for (map::iterator it = tempDeck->cards.begin(); it!=tempDeck->cards.end(); it++){ + MTGCard * c = tempDeck->getCardById(it->first); + for (int j = 0; j < it->second; j++){ + MTGCardInstance * card = NEW MTGCardInstance(c, NULL); + displayCards[i] = card; + display->AddCard(card); + i++; + } + } + delete tempDeck; + } + showPriceDialog = -1; + }else{ + //error not enough money + } + break; + case 2: + if (item->card){ + int rnd = (rand() % 25); + price = price - (rnd * price)/100; + pricelist->setPrice(item->card->getMTGId(),price); + } + showPriceDialog = -1; + break; + } +} + + +void ShopItems::safeDeleteDisplay(){ + if (!display) return; + for (int i = 0; i < display->mCount; i++){ + delete displayCards[i]; + } + SAFE_DELETE(display); +} + +void ShopItems::saveAll(){ + savePriceList(); + playerdata->save(); +} + +void ShopItems::savePriceList(){ + pricelist->save(); +} + +ShopItems::~ShopItems(){ + SAFE_DELETE(pricelist); + SAFE_DELETE(playerdata); + SAFE_DELETE(dialog); + safeDeleteDisplay(); + SAFE_DELETE(myCollection); +} + +ostream& ShopItem::toString(ostream& out) const +{ + return out << "ShopItem ::: mHasFocus : " << mHasFocus + << " ; mFont : " << mFont + << " ; mText : " << mText + << " ; quad : " << quad + << " ; thumb : " << thumb + << " ; mScale : " << mScale + << " ; mTargetScale : " << mTargetScale + << " ; nameCount : " << nameCount + << " ; quantity : " << quantity + << " ; card : " << card + << " ; price : " << price; +} diff --git a/projects/mtg/src/SimpleMenu.cpp b/projects/mtg/src/SimpleMenu.cpp index 31e8ae27f..377d4367a 100644 --- a/projects/mtg/src/SimpleMenu.cpp +++ b/projects/mtg/src/SimpleMenu.cpp @@ -9,11 +9,6 @@ const unsigned SimpleMenu::SIDE_SIZE = 7; const unsigned SimpleMenu::VMARGIN = 16; const unsigned SimpleMenu::HMARGIN = 30; const signed SimpleMenu::LINE_HEIGHT = 20; -const char* SimpleMenu::spadeLPath = "graphics/spade_ul.png"; -const char* SimpleMenu::spadeRPath = "graphics/spade_ur.png"; -const char* SimpleMenu::jewelPath = "graphics/jewel.png"; -const char* SimpleMenu::sidePath = "graphics/menuside.png"; -const char* SimpleMenu::titleFontPath = "graphics/smallface"; JQuad* SimpleMenu::spadeR = NULL; JQuad* SimpleMenu::spadeL = NULL; @@ -48,10 +43,10 @@ SimpleMenu::SimpleMenu(int id, JGuiListener* listener, JLBFont* font, int x, int JRenderer* renderer = JRenderer::GetInstance(); - if (!spadeLTex) spadeLTex= renderer->LoadTexture(spadeLPath, TEX_TYPE_USE_VRAM); - if (!spadeRTex) spadeRTex = renderer->LoadTexture(spadeRPath, TEX_TYPE_USE_VRAM); + if (!spadeLTex) spadeLTex= renderer->LoadTexture(options.themeGraphic("spade_ul.png").c_str(), TEX_TYPE_USE_VRAM); + if (!spadeRTex) spadeRTex = renderer->LoadTexture(options.themeGraphic("spade_ur.png").c_str(), TEX_TYPE_USE_VRAM); if (!jewelTex) jewelTex= renderer->CreateTexture(5, 5, TEX_TYPE_USE_VRAM); - if (!sideTex) sideTex = renderer->LoadTexture(sidePath, TEX_TYPE_USE_VRAM); + if (!sideTex) sideTex = renderer->LoadTexture(options.themeGraphic("menuside.png").c_str(), TEX_TYPE_USE_VRAM); if (NULL == spadeL) spadeL = NEW JQuad(spadeLTex, 2, 1, 16, 13); if (NULL == spadeR) spadeR = NEW JQuad(spadeRTex, 2, 1, 16, 13); if (NULL == jewel) jewel = NEW JQuad(jewelTex, 1, 1, 3, 3); @@ -59,8 +54,8 @@ if (NULL == spadeL) spadeL = NEW JQuad(spadeLTex, 2, 1, 16, 13); if (NULL == titleFont) { - GameApp::CommonRes->LoadJLBFont(titleFontPath, 7); - titleFont = GameApp::CommonRes->GetJLBFont(titleFontPath); + GameApp::CommonRes->LoadJLBFont(options.themeGraphic("smallface"), 7); + titleFont = GameApp::CommonRes->GetJLBFont(options.themeGraphic("smallface")); } if (NULL == stars) stars = NEW hgeParticleSystem("graphics/stars.psi", GameApp::CommonRes->GetQuad("stars")); @@ -110,14 +105,13 @@ void SimpleMenu::Render(){ selectionTargetY = selectionY = mY + VMARGIN; timeOpen = 0; } - mFont->SetColor(ARGB(255,255,255,255)); JRenderer * renderer = JRenderer::GetInstance(); float height = mHeight; if (timeOpen < 1) height *= timeOpen > 0 ? timeOpen : -timeOpen; - renderer->FillRect(mX, mY, mWidth, height, ARGB(180,0,0,0)); + renderer->FillRect(mX, mY, mWidth, height, options[Metrics::POPUP_MENU_FC].asColor(ARGB(180,0,0,0))); drawVertPole(mX, mY - 16, height + 32); drawVertPole(mX + mWidth, mY - 16, height + 32); @@ -136,10 +130,10 @@ void SimpleMenu::Render(){ { if (static_cast(mObjects[i])->hasFocus()){ GameApp::CommonRes->GetJLBFont(Constants::MAIN_FONT)->DrawString(static_cast(mObjects[i])->desc.c_str(),mX+mWidth+10,mY+15); - mFont->SetColor(ARGB(255,255,255,0)); + mFont->SetColor(options[Metrics::POPUP_MENU_TCH].asColor(ARGB(255,255,255,0))); } else - mFont->SetColor(ARGB(255,255,255,255)); + mFont->SetColor(options[Metrics::POPUP_MENU_TC].asColor(ARGB(150,255,255,255))); (static_cast(mObjects[i]))->RenderWithOffset(-LINE_HEIGHT*startId); } } diff --git a/projects/mtg/src/SimplePad.cpp b/projects/mtg/src/SimplePad.cpp new file mode 100644 index 000000000..81880ecb4 --- /dev/null +++ b/projects/mtg/src/SimplePad.cpp @@ -0,0 +1,426 @@ +#include "../include/config.h" +#include "../include/SimplePad.h" +#include "JTypes.h" +#include "../include/GameApp.h" +#include "../include/Translate.h" + + +#define ALPHA_COLUMNS 8 +#define ALPHA_ROWS 8 + +#define KPD_UP 0 +#define KPD_DOWN 1 +#define KPD_LEFT 2 +#define KPD_RIGHT 3 + +SimpleKey::SimpleKey( string _ds, int _id){ + displayValue = _ds; id = _id; + for(int x=0;x<4;x++) + adjacency[4] = KPD_NOWHERE; +} + +void SimplePad::linkKeys(int from, int to, int dir){ + + if(keys[from] && keys[to]){ + keys[from]->adjacency[dir] = to; + switch(dir){ + case KPD_UP: + case KPD_LEFT: + dir++; + break; + default: + dir--; + } + keys[to]->adjacency[dir] = from; + } +} + +SimplePad::SimplePad(bool numbers){ + nbitems = 0; + bActive = false; + selected = 0; + priorKey = 0; + cursor = 0; + bShowCancel = false; + bShowNumpad = false; + bCapslock = true; + char buf[2]; + buf[1] = '\0'; + SimpleKey * k; + + for(int x=0;x KPD_A) + k->adjacency[KPD_LEFT] = idx-1; + if(idx < KPD_Z) + k->adjacency[KPD_RIGHT] = idx+1; + if(idx > ALPHA_COLUMNS) + k->adjacency[KPD_UP] = idx-1-ALPHA_COLUMNS; + else + k->adjacency[KPD_UP] = KPD_INPUT; + if(idx < 25-ALPHA_COLUMNS) + k->adjacency[KPD_DOWN] = idx+1+ALPHA_COLUMNS; + } + + Add("Spacebar",KPD_SPACE); + + for(int x=25-ALPHA_COLUMNS;x<26;x++) + keys[x]->adjacency[KPD_DOWN] = KPD_SPACE; + + k=Add("Confirm",KPD_OK); + keys[KPD_Z]->adjacency[KPD_RIGHT] = KPD_OK; + k->adjacency[KPD_UP] = KPD_CAPS; + k->adjacency[KPD_LEFT] = KPD_Z; + k->adjacency[KPD_DOWN] = KPD_CANCEL; + + k=Add("Cancel",KPD_CANCEL); + k->adjacency[KPD_UP] = KPD_OK; + k->adjacency[KPD_LEFT] = KPD_SPACE; + + k=Add("Del",KPD_DEL); + keys[KPD_I]->adjacency[KPD_RIGHT] = KPD_DEL; + k->adjacency[KPD_UP] = KPD_9; + k->adjacency[KPD_DOWN] = KPD_CAPS; + k->adjacency[KPD_LEFT] = KPD_I; + + k=Add("Caps",KPD_CAPS); + keys[KPD_R]->adjacency[KPD_RIGHT] = KPD_CAPS; + keys[KPD_R]->adjacency[KPD_DOWN] = KPD_Z; + k->adjacency[KPD_UP] = KPD_DEL; + k->adjacency[KPD_DOWN] = KPD_OK; + k->adjacency[KPD_LEFT] = KPD_R; + + + for(int x=0;x<10;x++){ + buf[0] = '0'+x; + Add(buf,KPD_0+x); + if(x < 8) + linkKeys(KPD_0+x,KPD_A+x,KPD_DOWN); + if(x > 0) + linkKeys(KPD_0+x,KPD_0+x-1,KPD_LEFT); + } + + keys[KPD_8]->adjacency[KPD_DOWN] = KPD_DEL; + keys[KPD_9]->adjacency[KPD_DOWN] = KPD_DEL; + + keys[KPD_0]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_A]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_J]->adjacency[KPD_LEFT] = KPD_NOWHERE; + keys[KPD_S]->adjacency[KPD_LEFT] = KPD_NOWHERE; + +} + +SimplePad::~SimplePad() +{ + for(int x=0;x= KPD_MAX) + return NULL; + + keys[nbitems++] = NEW SimpleKey(display,id); + return keys[nbitems-1]; +} +void SimplePad::pressKey(unsigned char key){ + string input = ""; + int tCursor = cursor; + + if(isalpha(key)) { + if(bCapslock) + input += toupper(key); + else + input += key; + + if(cursor < 0 || cursor > buffer.size()) + tCursor = buffer.size(); + else + cursor++; + buffer.insert(tCursor,input); + } + else if(key == KPD_CAPS) + bCapslock = !bCapslock; + else if(key == KPD_DEL) { + if(cursor < 0 || cursor > buffer.size()) + cursor = buffer.size(); + if(cursor == buffer.size()) + buffer = buffer.substr(0,cursor-1); + else if(cursor > 0) + buffer = buffer.substr(0,cursor) + buffer.substr(cursor+1); + else + return; + + cursor--; + } + else if(key == KPD_OK) + Finish(); + else if(key == KPD_CANCEL) { + bCanceled = true; + Finish(); + } + +} +void SimplePad::MoveSelection(unsigned char moveto) +{ + if(!bShowNumpad && moveto >= KPD_0 && moveto <= KPD_9 ) + moveto = KPD_INPUT; + else if(!bShowCancel && moveto == KPD_CANCEL ) + moveto = KPD_SPACE; + + if(selected < KPD_MAX && selected >= 0) + priorKey = selected; + + if(moveto < KPD_MAX && moveto >= 0) { + selected = moveto; + } + else if(moveto == KPD_INPUT) + selected = KPD_INPUT; +} + +void SimplePad::Update(float dt){ + JGE * mEngine = JGE::GetInstance(); + + //We can always confirm! + if(mEngine->GetButtonClick(PSP_CTRL_START)) + { + if(selected != KPD_OK) + selected = KPD_OK; + else + Finish(); + return; + } + + if(selected == KPD_SPACE){ + if(bShowCancel && mEngine->GetButtonClick(PSP_CTRL_RIGHT)) + selected = KPD_CANCEL; + else if (mEngine->GetButtonClick(PSP_CTRL_LEFT)||mEngine->GetButtonClick(PSP_CTRL_RIGHT) + ||mEngine->GetButtonClick(PSP_CTRL_UP)||mEngine->GetButtonClick(PSP_CTRL_DOWN)) + selected = priorKey; + } //Moving in/from the text field. + else if(selected == KPD_INPUT){ + if (mEngine->GetButtonClick(PSP_CTRL_DOWN) ) + selected = priorKey; + if (mEngine->GetButtonClick(PSP_CTRL_LEFT) && cursor > -1){ + if(cursor > buffer.size()) + cursor = buffer.size() - 1; + else + cursor--; + } + else if (mEngine->GetButtonClick(PSP_CTRL_RIGHT)) + if(cursor < buffer.size()) + cursor++; + else + cursor = buffer.size() + 1; + } + else if(selected >= 0 && keys[selected]){ + if (mEngine->GetButtonClick(PSP_CTRL_LEFT)) + MoveSelection(keys[selected]->adjacency[KPD_LEFT]); + else if (mEngine->GetButtonClick(PSP_CTRL_RIGHT)) + MoveSelection(keys[selected]->adjacency[KPD_RIGHT]); + if (mEngine->GetButtonClick(PSP_CTRL_DOWN)) + MoveSelection(keys[selected]->adjacency[KPD_DOWN]); + else if (mEngine->GetButtonClick(PSP_CTRL_UP)) + MoveSelection(keys[selected]->adjacency[KPD_UP]); + } + + + //These bits require a valid key... + if(selected >= 0 && selected < nbitems && keys[selected]){ + if (mEngine->GetButtonClick(PSP_CTRL_CIRCLE)) + pressKey(keys[selected]->id); + } + if (mEngine->GetButtonClick(PSP_CTRL_CROSS) && buffer.size() > 0) + buffer = buffer.substr(0,buffer.size() - 1); + if (mEngine->GetButtonClick(PSP_CTRL_LTRIGGER)){ + if(buffer.size() != 0 && cursor != 0) + if(cursor < 0 || cursor >= buffer.size()) + cursor = buffer.size() - 1; + else + cursor--; + } + else if (mEngine->GetButtonClick(PSP_CTRL_RTRIGGER)){ + if(cursor > -1 && cursor < buffer.size()) + cursor++; + else{ + buffer += ' '; + cursor = buffer.size(); + } + } + + mX = 50; + mY = 50; + +} +void SimplePad::Start(string value, string * _dest) { + bActive = true; + bCanceled=false; + buffer = value; + original = buffer; + dest = _dest; + cursor = buffer.size(); +} + +string SimplePad::Finish() { + bActive = false; + if(bCanceled){ + dest = NULL; + return original; + } + if(dest != NULL){ + dest->clear(); dest->insert(0,buffer); + dest = NULL; + } + return buffer; +} + +void SimplePad::Render(){ + //This could use some cleaning up to make margins more explicit + JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3"); + + int offX = 0, offY = 0; + int kH = mFont->GetHeight(); + int hSpacing = mFont->GetStringWidth("W"); + int vSpacing = 0; + int kW = hSpacing; + + JRenderer * renderer = JRenderer::GetInstance(); + + + if(title != "") + vSpacing = kH+8; + else + vSpacing = 0; + + offY = vSpacing; + if(bShowNumpad) + offY += kH+14; + //Draw Keypad Background. + renderer->FillRoundRect(mX-kW,mY-kH,(kW+12)*11,(kH+14)*5+offY,2,options[Metrics::POPUP_MENU_FC].asColor(ARGB(180,0,0,0))); + offY = vSpacing; + //Draw text entry bubble + renderer->FillRoundRect(mX-kW/2,mY+offY,(kW+12)*9+kW/2,kH,2,options[Metrics::KEYPAD_FCH].asColor(ARGB(255,255,255,255))); + + //Draw text-entry title, if we've got one. + if(title != ""){ + mFont->DrawString(title.c_str(),mX,mY); + mY+=kH+12; + } + + //Draw cursor. + int cPos = cursor; + if(cPos > -1 && cPos < buffer.size()) + { + kW = mFont->GetStringWidth(buffer.substr(cPos,1).c_str()); + renderer->FillRoundRect(mX+mFont->GetStringWidth(buffer.substr(0,cPos).c_str()),mY+kH-4, + kW,4,2,options[Metrics::KEY_FCH].asColor(ARGB(150,150,150,0))); + } + else + { + cPos = buffer.size(); + renderer->FillRoundRect(mX+mFont->GetStringWidth(buffer.substr(0,cPos).c_str()),mY+kH-4, + kW,4,2,options[Metrics::KEY_FCH].asColor(ARGB(150,150,150,0))); + } + + mFont->SetColor(options[Metrics::KEYPAD_TC].asColor(ARGB(255,0,0,0))); + mFont->DrawString(buffer.c_str(),mX,mY); + offY += kH + 12; + + int rowLen[4]; + if(!bShowNumpad) + vSpacing -= kH + 12; + + for(int x=0;x= KPD_0 && x <= KPD_9 && !bShowNumpad)) + continue; + + switch(x){ + case KPD_0: + offX = 0; + offY = vSpacing; + break; + case KPD_9: + rowLen[0] = offX; + break; + case KPD_A: + offX = 0; + offY = vSpacing+(kH+12)*1; + break; + case KPD_Z: + rowLen[3] = offX; + break; + case KPD_J: + rowLen[1] = offX; + offX = 0; + offY = vSpacing+(kH+12)*2; + break; + case KPD_S: + rowLen[2] = offX; + offX = 0; + offY = vSpacing+(kH+12)*3; + break; + case KPD_SPACE: + offX = 0; + offY = vSpacing+(kH+12)*4; + break; + case KPD_OK: + offX = rowLen[1] + hSpacing; + offY = vSpacing+(kH+12)*3; + break; + case KPD_CANCEL: + offX = rowLen[1] + hSpacing; + offY = vSpacing+(kH+12)*4; + break; + case KPD_DEL: + offX = rowLen[1] + hSpacing; + offY = vSpacing+(kH+12)*1; + break; + case KPD_CAPS: + offX = rowLen[1] + hSpacing; + offY = vSpacing+(kH+12)*2; + break; + } + + kW = mFont->GetStringWidth(keys[x]->displayValue.c_str()); + //Render a key. + if(x != selected){ + renderer->FillRoundRect(mX+offX-4,mY+offY-4,kW+8,kH+4,2,options[Metrics::POPUP_MENU_FC].asColor(ARGB(180,50,50,50))); + mFont->SetColor(options[Metrics::POPUP_MENU_TCH].asColor(ARGB(255,255,255,0))); + } + else{ + renderer->FillRoundRect(mX+offX-4,mY+offY-4,kW+8,kH+4,2,options[Metrics::POPUP_MENU_FC].asColor(ARGB(255,100,100,100))); + mFont->SetColor(options[Metrics::POPUP_MENU_TC].asColor(ARGB(255,255,255,255))); + } + + char vkey[2]; + vkey[1] = '\0'; + vkey[0] = keys[x]->id; + + + if(isalpha(vkey[0])) { + if(bCapslock) vkey[0] = toupper(vkey[0]); + mFont->DrawString(vkey,mX+offX,mY+offY); + } + else + mFont->DrawString(keys[x]->displayValue.c_str(),mX+offX,mY+offY); + offX += kW + 14; + } +} + +int SimplePad::cursorPos(){ + if(cursor < 0 || cursor > buffer.size()) + return buffer.size(); + + return cursor; +} \ No newline at end of file diff --git a/projects/mtg/template.vcproj b/projects/mtg/template.vcproj index 550d1570d..ba83010c8 100644 --- a/projects/mtg/template.vcproj +++ b/projects/mtg/template.vcproj @@ -516,6 +516,10 @@ RelativePath=".\src\SimpleMenu.cpp" > + + @@ -865,6 +869,10 @@ RelativePath=".\include\SimpleMenu.h" > + +