Jeck - Profile and cache improvements, booster duplicate likelihood reduced.
* Cache now tracks missing textures for RetrieveQuad, not just RetrieveCard/RetrieveTexture. * Profile options are no longer overwritten when switching profiles. * Main menu notifies of alternate profile- "Database: X" becomes "Profile: Y of X cards." * Boosters iterates through cards, replacing duplicates. Stops after 15 tries to prevent infinite loops on small sets. * Very simplistic theme switcher, only displays when alternate themes are present.
This commit is contained in:
@@ -75,6 +75,7 @@ public:
|
||||
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));
|
||||
bool isDefault(); //Returns true when number is 0 abd string is "" or "default"
|
||||
GameOption(int value = 0);
|
||||
GameOption(string value);
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
string displayValue, id;
|
||||
int hasFocus;
|
||||
bool canSelect;
|
||||
bool bHidden;
|
||||
float x, y;
|
||||
float width, height;
|
||||
virtual ostream& toString(ostream& out)const;
|
||||
@@ -31,6 +32,7 @@ public:
|
||||
OptionItem( string _id, string _displayValue);
|
||||
virtual ~OptionItem() {};
|
||||
|
||||
virtual bool Selectable() {return (canSelect && !bHidden);};
|
||||
virtual void Entering();
|
||||
virtual bool Leaving();
|
||||
virtual void Update(float dt);
|
||||
@@ -69,6 +71,7 @@ class OptionString:public OptionItem{
|
||||
virtual ostream& toString(ostream& out) const;
|
||||
bool bShowValue;
|
||||
};
|
||||
|
||||
class OptionNewProfile:public OptionString{
|
||||
public:
|
||||
OptionNewProfile(string _id, string _displayValue) : OptionString(_id, _displayValue) {bShowValue=false;};
|
||||
@@ -118,6 +121,11 @@ private:
|
||||
string root;
|
||||
};
|
||||
|
||||
class OptionTheme:public OptionDirectory{
|
||||
public:
|
||||
OptionTheme();
|
||||
};
|
||||
|
||||
class OptionProfile:public OptionDirectory{
|
||||
public:
|
||||
OptionProfile(GameApp * _app);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "MTGCard.h"
|
||||
|
||||
#define CACHE_SIZE_PIXELS 2000000
|
||||
#define MAX_CACHE_OBJECTS 100
|
||||
#define MAX_CACHE_OBJECTS 200
|
||||
|
||||
class WCachedResource{
|
||||
public:
|
||||
@@ -84,6 +84,7 @@ public:
|
||||
|
||||
void ClearMisses();
|
||||
void ClearUnlocked();
|
||||
void ClearSamples();
|
||||
void Refresh(); //Refreshes all files in cache, for when mode/profile changes.
|
||||
|
||||
unsigned int nowTime();
|
||||
@@ -111,7 +112,6 @@ private:
|
||||
bool RemoveOldestTexture();
|
||||
bool RemoveOldestSample();
|
||||
bool cleanup();
|
||||
void clearSamples();
|
||||
|
||||
WCachedTexture * getCachedTexture(string filename, bool makenew = true, int mode = 0, int format = TEXTURE_FORMAT);
|
||||
WCachedTexture * getCachedCard(MTGCard * card, int type = CACHE_CARD, bool makenew = true);
|
||||
@@ -121,6 +121,8 @@ private:
|
||||
//For cached stuff
|
||||
map<string,WCachedTexture*> textureCache;
|
||||
map<string,WCachedSample*> sampleCache;
|
||||
|
||||
vector<string> mTextureMissing; //For managed textures.
|
||||
|
||||
//Current access time.
|
||||
int lastTime;
|
||||
|
||||
@@ -77,6 +77,19 @@ const string Metrics::KEYPAD_TC = "_tKeypadTC";
|
||||
GameOption::GameOption(int value) : number(value){}
|
||||
GameOption::GameOption(string value) : str(value){}
|
||||
|
||||
bool GameOption::isDefault(){
|
||||
if(number != 0)
|
||||
return false;
|
||||
|
||||
string test = str;
|
||||
std::transform(test.begin(),test.end(),test.begin(),::tolower);
|
||||
|
||||
if(!test.size() || test == "default")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PIXEL_TYPE GameOption::asColor(PIXEL_TYPE fallback)
|
||||
{
|
||||
unsigned char color[4];
|
||||
@@ -177,14 +190,9 @@ GameSettings::GameSettings()
|
||||
//Load global options
|
||||
globalOptions = NEW GameOptions(GLOBAL_SETTINGS);
|
||||
|
||||
//Load profile options.
|
||||
string temp = (*globalOptions)[Options::ACTIVE_PROFILE.substr(2)].str;
|
||||
if(temp == "")
|
||||
temp = "Default";
|
||||
(*globalOptions)[Options::ACTIVE_PROFILE.substr(2)].str = temp;
|
||||
|
||||
themeOptions = NULL;
|
||||
profileOptions = NULL;
|
||||
themeOptions = NULL;
|
||||
|
||||
checkProfile();
|
||||
}
|
||||
|
||||
@@ -227,8 +235,9 @@ string GameSettings::profileFile(string filename, string fallback,bool sanity, b
|
||||
{
|
||||
char buf[512];
|
||||
string profile =(*this)[Options::ACTIVE_PROFILE].str;
|
||||
std::transform(profile.begin(),profile.end(),profile.begin(),::tolower);
|
||||
|
||||
if(profile != "" && profile != "Default") {
|
||||
if(profile != "" && profile != "default") {
|
||||
//No file, return root of profile directory
|
||||
if(filename == ""){
|
||||
sprintf(buf,"%sprofiles/%s",( relative ? "" : RESPATH"/" ),profile.c_str());
|
||||
@@ -262,13 +271,9 @@ string GameSettings::profileFile(string filename, string fallback,bool sanity, b
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GameSettings::checkProfile(){
|
||||
//Load current profile's options. Doesn't save prior set.
|
||||
|
||||
//Load current profile's options. Doesn't save prior set.
|
||||
char buf[512];
|
||||
SAFE_DELETE(profileOptions);
|
||||
|
||||
//Force our directories to exist.
|
||||
MAKEDIR(RESPATH"/profiles");
|
||||
@@ -277,14 +282,17 @@ void GameSettings::checkProfile(){
|
||||
temp+="/stats";
|
||||
MAKEDIR(temp.c_str());
|
||||
temp = profileFile(PLAYER_SETTINGS,"",false);
|
||||
|
||||
SAFE_DELETE(profileOptions);
|
||||
profileOptions = NEW GameOptions(temp);
|
||||
|
||||
|
||||
//Force a theme.
|
||||
temp = (*profileOptions)[Options::ACTIVE_THEME].str;
|
||||
if(temp == ""){
|
||||
if((*profileOptions)[Options::ACTIVE_THEME].isDefault()){
|
||||
temp = "Default";
|
||||
(*profileOptions)[Options::ACTIVE_THEME].str = "Default";
|
||||
}else{
|
||||
temp = (*profileOptions)[Options::ACTIVE_THEME].str;
|
||||
}
|
||||
|
||||
//Load theme options
|
||||
@@ -295,7 +303,7 @@ void GameSettings::checkProfile(){
|
||||
}
|
||||
|
||||
SAFE_DELETE(themeOptions);
|
||||
themeOptions = NEW GameOptions(buf);
|
||||
themeOptions = NEW GameOptions(buf);
|
||||
|
||||
//Validation of collection, etc, only happens if the game is up.
|
||||
if(theGame == NULL || theGame->collection == NULL)
|
||||
@@ -323,6 +331,7 @@ void GameSettings::checkProfile(){
|
||||
profileOptions->save();
|
||||
createUsersFirstDeck(setId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GameSettings::createUsersFirstDeck(int setId){
|
||||
|
||||
@@ -149,6 +149,14 @@ void GameStateMenu::Start(){
|
||||
mMovingW->SetHotSpot(72,16);
|
||||
JRenderer::GetInstance()->ResetPrivateVRAM();
|
||||
JRenderer::GetInstance()->EnableVSync(true);
|
||||
|
||||
//How many cards total ?
|
||||
PlayerData * playerdata = NEW PlayerData(mParent->collection);
|
||||
if(!options[Options::ACTIVE_PROFILE].isDefault())
|
||||
sprintf(nbcardsStr, "%s: %i of %i cards", options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards());
|
||||
else
|
||||
sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards());
|
||||
SAFE_DELETE(playerdata);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +229,7 @@ void GameStateMenu::fillScroller(){
|
||||
|
||||
PlayerData * playerdata = NEW PlayerData(mParent->collection);
|
||||
sprintf(buff2, _("You currently have %i credits").c_str(),playerdata->credits);
|
||||
delete playerdata;
|
||||
SAFE_DELETE(playerdata);
|
||||
scroller->Add(buff2);
|
||||
|
||||
scroller->Add(_("More cards and mods at http://wololo.net/wagic"));
|
||||
@@ -282,9 +290,6 @@ void GameStateMenu::Update(float dt)
|
||||
mReadConf = 1;
|
||||
}
|
||||
if (!nextDirectory(RESPATH"/sets/","_cards.dat")){
|
||||
//How many cards total ?
|
||||
sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards());
|
||||
|
||||
//Force default, if necessary.
|
||||
if(options[Options::ACTIVE_PROFILE].str == "")
|
||||
options[Options::ACTIVE_PROFILE].str = "Default";
|
||||
@@ -304,8 +309,16 @@ void GameStateMenu::Update(float dt)
|
||||
currentState = MENU_STATE_MAJOR_FIRST_TIME | MENU_STATE_MINOR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
//List active profile and database size.
|
||||
PlayerData * playerdata = NEW PlayerData(mParent->collection);
|
||||
if(!options[Options::ACTIVE_PROFILE].isDefault())
|
||||
sprintf(nbcardsStr, "%s: %i of %i cards", options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards());
|
||||
else
|
||||
sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards());
|
||||
SAFE_DELETE(playerdata);
|
||||
resetDirectory();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MENU_STATE_MAJOR_FIRST_TIME :
|
||||
options.checkProfile();
|
||||
|
||||
@@ -43,11 +43,13 @@ void GameStateOptions::Start()
|
||||
optionsTabs->Add(optionsList);
|
||||
|
||||
optionsList = NEW OptionsList("Profiles");
|
||||
OptionProfile * pickProf = NEW OptionProfile(mParent);
|
||||
optionsList->Add(pickProf);
|
||||
OptionNewProfile * key = NEW OptionNewProfile("","New Profile");
|
||||
key->bShowValue = false;
|
||||
optionsList->Add(key);
|
||||
OptionProfile * pickProf = NEW OptionProfile(mParent);
|
||||
optionsList->Add(pickProf);
|
||||
OptionTheme * theme = NEW OptionTheme();
|
||||
optionsList->Add(theme);
|
||||
|
||||
optionsTabs->Add(optionsList);
|
||||
optionsList = NEW OptionsList("Credits");
|
||||
|
||||
@@ -39,6 +39,7 @@ OptionItem::OptionItem( string _id, string _displayValue) {
|
||||
displayValue = _(_displayValue);
|
||||
canSelect=true;
|
||||
hasFocus=false;
|
||||
bHidden=false;
|
||||
width = SCREEN_WIDTH;
|
||||
height = 20;
|
||||
}
|
||||
@@ -406,7 +407,7 @@ void OptionsList::Entering(){
|
||||
//Try to force a selectable option.
|
||||
if(current == -1){
|
||||
for (int i = 0 ; i < nbitems; i++){
|
||||
if(listItems[i]->canSelect) {
|
||||
if(listItems[i]->Selectable()) {
|
||||
current = i;
|
||||
listItems[current]->Entering();
|
||||
break;
|
||||
@@ -440,7 +441,7 @@ void OptionsList::Render(){
|
||||
//Force a selectable option.
|
||||
if(current == -1){
|
||||
for (int i = 0 ; i < nbitems; i++){
|
||||
if(listItems[i]->canSelect) {
|
||||
if(listItems[i]->Selectable()) {
|
||||
current = i;
|
||||
listItems[current]->Entering();
|
||||
break;
|
||||
@@ -450,7 +451,7 @@ void OptionsList::Render(){
|
||||
//Find out how large our list is.
|
||||
for (int pos=0;pos < nbitems; pos++){
|
||||
listHeight+=listItems[pos]->height+5;
|
||||
if(listItems[pos]->canSelect){
|
||||
if(listItems[pos]->Selectable()){
|
||||
listSelectable++;
|
||||
if(pos < current) adjustedCurrent++;
|
||||
}
|
||||
@@ -460,14 +461,20 @@ void OptionsList::Render(){
|
||||
if(listHeight > SCREEN_HEIGHT)
|
||||
{
|
||||
width -= 10;
|
||||
for (start=current;start > 0; start--) {
|
||||
for (start=current;start > 0; start--){
|
||||
if(listItems[start]->bHidden)
|
||||
continue;
|
||||
|
||||
vHeight += listItems[start]->height+5;
|
||||
if(vHeight >= (SCREEN_HEIGHT-60)/2)
|
||||
break;
|
||||
}
|
||||
vHeight = 0;
|
||||
for (nowPos=nbitems;nowPos > 1; nowPos--)
|
||||
for (nowPos=nbitems;nowPos > 1; nowPos--){
|
||||
if(listItems[start]->bHidden)
|
||||
continue;
|
||||
vHeight += listItems[nowPos-1]->height+5;
|
||||
}
|
||||
|
||||
if(vHeight <= SCREEN_HEIGHT-40 && nowPos < start)
|
||||
start = nowPos;
|
||||
@@ -481,6 +488,9 @@ void OptionsList::Render(){
|
||||
if(start >= 0)
|
||||
{
|
||||
for (int pos=0;pos < nbitems; pos++){
|
||||
if(listItems[pos]->bHidden)
|
||||
continue;
|
||||
|
||||
if(pos < start){
|
||||
vHeight += listItems[pos]->height + 5;
|
||||
continue;
|
||||
@@ -523,9 +533,9 @@ void OptionsList::Update(float dt){
|
||||
{
|
||||
if (potential > 0){
|
||||
potential--;
|
||||
while(potential > 0 && listItems[potential]->canSelect == false)
|
||||
while(potential > 0 && listItems[potential]->Selectable() == false)
|
||||
potential--;
|
||||
if(potential < 0 || !listItems[potential]->canSelect)
|
||||
if(potential < 0 || !listItems[potential]->Selectable())
|
||||
potential = -1;
|
||||
else if(listItems[current]->Leaving()){
|
||||
current = potential;
|
||||
@@ -537,9 +547,9 @@ void OptionsList::Update(float dt){
|
||||
{
|
||||
if (potential < nbitems-1){
|
||||
potential++;
|
||||
while(potential < nbitems-1 && listItems[potential]->canSelect == false)
|
||||
while(potential < nbitems-1 && listItems[potential]->Selectable() == false)
|
||||
potential++;
|
||||
if(potential == nbitems || !listItems[potential]->canSelect)
|
||||
if(potential == nbitems || !listItems[potential]->Selectable())
|
||||
potential = -1;
|
||||
else if(potential != current && listItems[current]->Leaving()){
|
||||
current = potential;
|
||||
@@ -647,7 +657,7 @@ bool OptionsMenu::isTab(string name){
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
int OptionsMenu::Submode()
|
||||
{
|
||||
@@ -664,8 +674,8 @@ void OptionsMenu::acceptSubmode()
|
||||
}
|
||||
void OptionsMenu::reloadValues()
|
||||
{
|
||||
if(current > -1 && current < nbitems)
|
||||
tabs[current]->reloadValues();
|
||||
for(int i=0;i<nbitems;i++)
|
||||
tabs[i]->reloadValues();
|
||||
}
|
||||
|
||||
void OptionsMenu::cancelSubmode()
|
||||
@@ -764,12 +774,13 @@ int OptionNewProfile::Submode(){
|
||||
}
|
||||
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
|
||||
@@ -778,3 +789,12 @@ return out << "OptionString ::: displayValue : " << displayValue
|
||||
<< " ; hasFocus : " << hasFocus
|
||||
<< " ; x,y : " << x << "," << y;
|
||||
}
|
||||
|
||||
OptionTheme::OptionTheme(): OptionDirectory(RESPATH"/themes",Options::ACTIVE_THEME, "Current Theme"){
|
||||
addSelection("Default");
|
||||
sort(selections.begin(),selections.end());
|
||||
initSelections();
|
||||
hasFocus=false;
|
||||
if(selections.size() == 1)
|
||||
bHidden = true;
|
||||
}
|
||||
@@ -364,6 +364,22 @@ void ShopItems::ButtonPressed(int controllerId, int controlId){
|
||||
tempDeck->addRandomCards(3, sets,1,Constants::RARITY_U);
|
||||
tempDeck->addRandomCards(11, sets,1,Constants::RARITY_C);
|
||||
|
||||
//Check for duplicates. Does not guarentee none, just makes them extremely unlikely.
|
||||
//Code is kind of inefficient, but shouldn't be used often enough to matter.
|
||||
int loops=0;
|
||||
for(map<int,int>::iterator it = tempDeck->cards.begin();it!= tempDeck->cards.end() && loops < 15;it++,loops++){
|
||||
int dupes = it->second - 1;
|
||||
if(dupes <= 0)
|
||||
continue;
|
||||
|
||||
for(int x=0;x<dupes;x++)
|
||||
tempDeck->remove(it->first);
|
||||
|
||||
int rarity = (int) tempDeck->database->getCardById(it->first)->getRarity();
|
||||
tempDeck->addRandomCards(dupes,&rarity);
|
||||
it = tempDeck->cards.begin();
|
||||
}
|
||||
|
||||
playerdata->collection->add(tempDeck);
|
||||
myCollection->Add(tempDeck);
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ unsigned int WResourceManager::nowTime(){
|
||||
return ++lastTime;
|
||||
}
|
||||
|
||||
void WResourceManager::clearSamples(){
|
||||
void WResourceManager::ClearSamples(){
|
||||
map<string,WCachedSample*>::iterator next;
|
||||
for(map<string,WCachedSample*>::iterator it = sampleCache.begin();it!=sampleCache.end();it=next){
|
||||
next = it;
|
||||
@@ -208,7 +208,7 @@ WCachedSample * WResourceManager::getCachedSample(string filename, bool makenew)
|
||||
csample->sample = JSoundSystem::GetInstance()->LoadSample(sfile.c_str());
|
||||
//Potential cache overflow- clean the cache
|
||||
if(!csample->sample && fileExists(sfile.c_str())){
|
||||
clearSamples();
|
||||
ClearSamples();
|
||||
csample->sample = JSoundSystem::GetInstance()->LoadSample(sfile.c_str());
|
||||
}
|
||||
}
|
||||
@@ -450,6 +450,11 @@ JQuad * WResourceManager::RetrieveCard(MTGCard * card, int type, int style){
|
||||
|
||||
JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY, float width, float height, string resname, int style){
|
||||
|
||||
for(vector<string>::iterator it=mTextureMissing.begin();it!=mTextureMissing.end();it++){
|
||||
if((*it) == filename)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(resname == "")
|
||||
resname = filename;
|
||||
|
||||
@@ -504,7 +509,8 @@ JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY,
|
||||
return tc->GetQuad(offX,offY,width,height);
|
||||
}
|
||||
|
||||
//Texture doesn't exist, so no quad.
|
||||
//Texture doesn't exist, so no quad. Record miss.
|
||||
mTextureMissing.push_back(filename);
|
||||
return NULL;
|
||||
}
|
||||
void WResourceManager::Release(JTexture * tex){
|
||||
@@ -578,6 +584,13 @@ JTexture * WResourceManager::RetrieveTexture(string filename, int style){
|
||||
else
|
||||
tc = getCachedTexture(filename);
|
||||
}
|
||||
|
||||
if(style == RETRIEVE_MANAGE){
|
||||
for(vector<string>::iterator it = mTextureMissing.begin();it!=mTextureMissing.end();it++){
|
||||
if((*it) == filename)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//Perform lock or unlock on entry.
|
||||
if(style != RETRIEVE_MANAGE && tc){
|
||||
@@ -598,8 +611,13 @@ JTexture * WResourceManager::RetrieveTexture(string filename, int style){
|
||||
textureCache.erase(it);
|
||||
}
|
||||
//Pop texture into resource manager
|
||||
CreateTexture(filename);
|
||||
return GetTexture(filename);
|
||||
int val = CreateTexture(filename);
|
||||
if(val == INVALID_ID){
|
||||
mTextureMissing.push_back(filename);
|
||||
return NULL;//file not found
|
||||
}
|
||||
|
||||
return GetTexture(val);
|
||||
}
|
||||
|
||||
//Texture exists! Get it.
|
||||
@@ -863,7 +881,8 @@ int WResourceManager::fileOK(string filename, bool relative){
|
||||
}
|
||||
|
||||
int WResourceManager::CreateTexture(const string &textureName) {
|
||||
map<string, int>::iterator itr = mTextureMap.find(textureName);
|
||||
int id = INVALID_ID;
|
||||
map<string, int>::iterator itr = mTextureMap.find(textureName);
|
||||
|
||||
if (itr == mTextureMap.end())
|
||||
{
|
||||
@@ -873,14 +892,18 @@ int WResourceManager::CreateTexture(const string &textureName) {
|
||||
|
||||
JTexture *tex = JRenderer::GetInstance()->LoadTexture(path.c_str());
|
||||
|
||||
if (tex == NULL)
|
||||
return INVALID_ID;
|
||||
|
||||
int id = mTextureList.size();
|
||||
if (tex != NULL)
|
||||
{
|
||||
id = mTextureList.size();
|
||||
mTextureList.push_back(tex);
|
||||
mTextureMap[textureName] = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
else
|
||||
return itr->second;
|
||||
@@ -1000,7 +1023,9 @@ void WResourceManager::Refresh(){
|
||||
vector<JQuad*>::iterator q;
|
||||
JTexture * oldtex;
|
||||
|
||||
mTextureMissing.clear();
|
||||
ClearMisses();
|
||||
ClearSamples();
|
||||
|
||||
for(it = textureCache.begin();it!=textureCache.end();it++){
|
||||
if(it->second == NULL)
|
||||
|
||||
Reference in New Issue
Block a user