Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
48 KB
Referenced Files
None
Subscribers
None
diff --git a/src/Functions.cpp b/src/Functions.cpp
index 73247a8..000c0c1 100644
--- a/src/Functions.cpp
+++ b/src/Functions.cpp
@@ -1,934 +1,949 @@
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
#include <SDL/SDL_gfxPrimitives.h>
#include <string>
#include "Globals.h"
#include "Functions.h"
#include "FileManager.h"
#include "Objects.h"
#include "Player.h"
#include "GameObjects.h"
#include "Levels.h"
#include "TitleMenu.h"
#include "LevelEditor.h"
#include "Game.h"
#include "LevelSelect.h"
#include "Addons.h"
#include "ImageManager.h"
#include "MusicManager.h"
#include "ThemeManager.h"
#include "GUIListBox.h"
using namespace std;
#ifdef WIN32
#include <windows.h>
#include <shlobj.h>
#else
#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#endif
//Initialise the imagemanager.
//The ImageManager is used to prevent loading images multiple times.
ImageManager imageManager;
//Initialise the musicManager.
//The MusicManager is used to prevent loading music files multiple times and for playing/fading music.
MusicManager musicManager;
//Pointer to the settings object.
//It is used to load and save the settings file and change the settings.
Settings* settings=0;
SDL_Surface* loadImage(string file){
//We use the imageManager to load the file.
return imageManager.loadImage(file);
}
void applySurface(int x,int y,SDL_Surface* source,SDL_Surface* dest,SDL_Rect* clip){
//The offset is needed to draw at the right location.
SDL_Rect offset;
offset.x=x;
offset.y=y;
//Let SDL do the drawing of the surface.
SDL_BlitSurface(source,clip,dest,&offset);
}
void drawRect(int x,int y,int w,int h,SDL_Surface* dest,Uint32 color){
//NOTE: We let SDL_gfx render it.
rectangleRGBA(dest,x,y,x+w,y+h,color >> 24,color >> 16,color >> 8,255);
}
-//Draw "anti-aliased" borders and white background using SDL_gfx.
+//Draw a box with anti-aliased borders using SDL_gfx.
void drawGUIBox(int x,int y,int w,int h,SDL_Surface* dest,Uint32 color){
+ //Fill content's background color from function parameter
boxRGBA(screen,x+1,y+1,x+w-2,y+h-2,color >> 24,color >> 16,color >> 8,color >> 0);
- rectangleRGBA(screen,x,y,x+w-1,y+h-1,0,0,0,160);
- rectangleRGBA(screen,x+1,y+1,x+w-2,y+h-2,0,0,0,64);
-
+
+ //Draw first black borders around content and leave 1 pixel in every corner
lineRGBA(screen,x+1,y,x+w-2,y,0,0,0,255);
lineRGBA(screen,x+1,y+h-1,x+w-2,y+h-1,0,0,0,255);
lineRGBA(screen,x,y+1,x,y+h-2,0,0,0,255);
lineRGBA(screen,x+w-1,y+1,x+w-1,y+h-2,0,0,0,255);
+
+ //Fill the corners with transperent color to create anti-aliased borders
+ pixelRGBA(screen,x,y,0,0,0,160);
+ pixelRGBA(screen,x,y+h-1,0,0,0,160);
+ pixelRGBA(screen,x+w-1,y,0,0,0,160);
+ pixelRGBA(screen,x+w-1,y+h-1,0,0,0,160);
+
+ //Draw second lighter border around content
+ rectangleRGBA(screen,x+1,y+1,x+w-2,y+h-2,0,0,0,64);
+
+ //Create anti-aliasing in corners of second border
+ pixelRGBA(screen,x+1,y+1,0,0,0,50);
+ pixelRGBA(screen,x+1,y+h-2,0,0,0,50);
+ pixelRGBA(screen,x+w-2,y+1,0,0,0,50);
+ pixelRGBA(screen,x+w-2,y+h-2,0,0,0,50);
}
void drawLine(int x1,int y1,int x2,int y2,SDL_Surface* dest,Uint32 color){
//NOTE: We let SDL_gfx render it.
lineRGBA(dest,x1,y1,x2,y2,color >> 24,color >> 16,color >> 8,255);
}
void drawLineWithArrow(int x1,int y1,int x2,int y2,SDL_Surface* dest,Uint32 color,int spacing,int offset,int xsize,int ysize){
//Draw line first
drawLine(x1,y1,x2,y2,dest,color);
//calc delta and length
double dx=x2-x1;
double dy=y2-y1;
double length=sqrt(dx*dx+dy*dy);
if(length<0.001) return;
//calc the unit vector
dx/=length; dy/=length;
//Now draw arrows on it
for(double p=offset;p<length;p+=spacing){
drawLine(int(x1+p*dx+0.5),int(y1+p*dy+0.5),
int(x1+(p-xsize)*dx-ysize*dy+0.5),int(y1+(p-xsize)*dy+ysize*dx+0.5),dest,color);
drawLine(int(x1+p*dx+0.5),int(y1+p*dy+0.5),
int(x1+(p-xsize)*dx+ysize*dy+0.5),int(y1+(p-xsize)*dy-ysize*dx+0.5),dest,color);
}
}
bool init(){
//Initialze SDL.
if(SDL_Init(SDL_INIT_EVERYTHING)==-1) {
fprintf(stderr,"FATAL ERROR: SDL_Init failed\n");
return false;
}
//Initialze SDL_mixer (audio).
if(Mix_OpenAudio(22050,MIX_DEFAULT_FORMAT,2,512)==-1){
fprintf(stderr,"FATAL ERROR: Mix_OpenAudio failed\n");
return false;
}
//Initialze SDL_ttf (fonts).
if(TTF_Init()==-1){
fprintf(stderr,"FATAL ERROR: TTF_Init failed\n");
return false;
}
//Initialise the screen.
screen=SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_HWSURFACE | SDL_DOUBLEBUF /*|SDL_FULLSCREEN*/ );
if(screen==NULL){
fprintf(stderr,"FATAL ERROR: SDL_SetVideoMode failed\n");
return false;
}
//Set the the window caption.
SDL_WM_SetCaption(("Me and my shadow "+version).c_str(),NULL);
SDL_EnableUNICODE(1);
//Create the types of blocks.
for(int i=0;i<TYPE_MAX;i++){
Game::blockNameMap[Game::blockName[i]]=i;
}
//Nothing went wrong so we return true.
return true;
}
bool loadFiles(){
//Load the music and play it.
if(musicManager.loadMusic((getDataPath()+"music/menu.music")).empty()){
printf("WARNING: Unable to load background music! \n");
}
musicManager.playMusic("menu",false);
//Always load the default music list for fallback.
musicManager.loadMusicList((getDataPath()+"music/default.list"));
//Load the fonts.
fontTitle=TTF_OpenFont((getDataPath()+"font/knewave.ttf").c_str(),55);
fontGUI=TTF_OpenFont((getDataPath()+"font/knewave.ttf").c_str(),32);
fontText=TTF_OpenFont((getDataPath()+"font/Blokletters-Viltstift.ttf").c_str(),20);
if(fontTitle==NULL || fontGUI==NULL || fontText==NULL){
printf("ERROR: Unable to load fonts! \n");
return false;
}
//Load the default theme.
if(objThemes.appendThemeFromFile(getDataPath()+"themes/Cloudscape/theme.mnmstheme")==NULL){
printf("ERROR: Can't load default theme file\n");
return false;
}
//Nothing failed so return true.
return true;
}
bool loadSettings(){
settings=new Settings(getUserPath()+"meandmyshadow.cfg");
settings->parseFile();
//Always return true?
return true;
}
bool saveSettings(){
settings->save();
//Always return true?
return true;
}
Settings* getSettings(){
return settings;
}
MusicManager* getMusicManager(){
return &musicManager;
}
void clean(){
//We delete the settings.
if(settings){
delete settings;
settings=NULL;
}
//Get rid of the currentstate/
//NOTE: The state is probably already deleted by the changeState function.
if(currentState)
delete currentState;
//Destroy the GUI if present.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Destroy the imageManager.
imageManager.destroy();
//Destroy the musicManager.
musicManager.destroy();
//Close the fonts and quit SDL_ttf.
TTF_CloseFont(fontTitle);
TTF_CloseFont(fontGUI);
TTF_CloseFont(fontText);
TTF_Quit();
//Quit SDL.
SDL_Quit();
//And finally stop audio.
Mix_CloseAudio();
}
void setNextState(int newstate){
//Only change the state when we aren't already exiting.
if(nextState!=STATE_EXIT){
nextState=newstate;
}
}
void changeState(){
//Check if there's a nextState.
if(nextState!=STATE_NULL){
//Delete the currentState.
delete currentState;
currentState=NULL;
//Set the currentState to the nextState.
stateID=nextState;
nextState=STATE_NULL;
//Init the state.
switch(stateID){
case STATE_GAME:
currentState=new Game();
break;
case STATE_MENU:
levels.clear();
currentState=new Menu();
break;
case STATE_LEVEL_SELECT:
currentState=new LevelSelect();
break;
case STATE_LEVEL_EDITOR:
//Start without levels in the leveleditor.
levels.clear();
currentState=new LevelEditor();
break;
case STATE_OPTIONS:
currentState=new Options();
break;
case STATE_ADDONS:
currentState=new Addons();
break;
}
//NOTE: STATE_EXIT isn't mentioned, meaning that currentState is null.
//This way the game loop will break and the program will exit.
//Fade out.
int fade=255;
SDL_BlitSurface(screen,NULL,tempSurface,NULL);
while(fade>0){
fade-=17;
if(fade<0)
fade=0;
SDL_FillRect(screen,NULL,0);
SDL_SetAlpha(tempSurface, SDL_SRCALPHA, fade);
SDL_BlitSurface(tempSurface,NULL,screen,NULL);
SDL_Flip(screen);
SDL_Delay(25);
}
}
}
void musicStoppedHook(){
//We just call the musicStopped method of the MusicManager.
musicManager.musicStopped();
}
bool checkCollision(const SDL_Rect& a,const SDL_Rect& b){
//Check if the left side of box a isn't past the right side of b.
if(a.x>=b.x+b.w){
return false;
}
//Check if the right side of box a isn't left of the left side of b.
if(a.x+a.w<=b.x){
return false;
}
//Check if the top side of box a isn't under the bottom side of b.
if(a.y>=b.y+b.h){
return false;
}
//Check if the bottom side of box a isn't above the top side of b.
if(a.y+a.h<=b.y){
return false;
}
//We have collision.
return true;
}
void setCamera(){
//SetCamera only works in the Level editor.
if(stateID==STATE_LEVEL_EDITOR){
//Get the mouse coordinates.
int x,y;
SDL_GetMouseState(&x,&y);
//Make sure we avoid the toolbar.
SDL_Rect mouse={x,y,0,0};
SDL_Rect toolbar={155,550,510,50};
if(checkCollision(mouse,toolbar))
return;
//Check if the mouse is near the left edge of the screen.
//Else check if the mouse is near the right edge.
if(x<50){
//We're near the left edge so move the camera.
camera.x-=5;
}else if(x>SCREEN_WIDTH-50){
//We're near the right edge so move the camera.
camera.x+=5;
}
//Check if the mouse is near the top edge of the screen.
//Else check if the mouse is near the bottom edge.
if(y<50){
//We're near the top edge so move the camera.
camera.y-=5;
}else if(y>SCREEN_HEIGHT-50){
//We're near the bottom edge so move the camera.
camera.y+=5;
}
}
}
bool parseArguments(int argc, char** argv){
//Loop through all arguments.
//We start at one since 0 is the command itself.
for(int i=1;i<argc;i++){
string argument=argv[i];
//Check if the argument is the data-dir.
if(argument=="--data-dir"){
//We need a second argument so we increase i.
i++;
if(i>=argc){
printf("ERROR: Missing argument for command '%s'\n\n",argument.c_str());
return false;
}
//Configure the dataPath with the given path.
dataPath=argv[i];
if(!getDataPath().empty()){
char c=dataPath[dataPath.size()-1];
if(c!='/'&&c!='\\') dataPath+="/";
}
}else if(argument=="--user-dir"){
//We need a second argument so we increase i.
i++;
if(i>=argc){
printf("ERROR: Missing argument for command '%s'\n\n",argument.c_str());
return false;
}
//Configure the userPath with the given path.
userPath=argv[i];
if(!userPath.empty()){
char c=userPath[userPath.size()-1];
if(c!='/'&&c!='\\') userPath+="/";
}
}else if(argument=="-v" || argument=="-version" || argument=="--version"){
//Print the version.
printf("Version: '%s'\n\n",version.c_str());
}else if(argument=="-h" || argument=="-help" || argument=="--help"){
//If the help is requested we'll return false without printing an error.
//This way the usage/help text will be printed.
return false;
}else{
//Any other argument is unknow so we return false.
printf("ERROR: Unknown argument %s\n\n",argument.c_str());
return false;
}
}
//If everything went well we can return true.
return true;
}
//Special structure that will recieve the GUIEventCallbacks of the messagebox.
struct msgBoxHandler:public GUIEventCallback{
public:
//Integer containing the ret(urn) value of the messageBox.
int ret;
public:
//Constructor.
msgBoxHandler():ret(0){}
void GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
//Make sure it's a click event.
if(eventType==GUIEventClick){
//Set the return value.
ret=obj->value;
//After a click event we can delete the GUI.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
}
};
msgBoxResult msgBox(string prompt,msgBoxButtons buttons,const string& title){
//Create the event handler.
msgBoxHandler objHandler;
//The GUI objects.
GUIObject* obj;
//We keep a pointer to the original GUIObjectRoot for later.
GUIObject* tmp=GUIObjectRoot;
//Create the GUIObjectRoot, the height and y location is temp.
//It depends on the content what it will be.
GUIObjectRoot=new GUIObject(100,200,600,200,GUIObjectFrame,title.c_str());
//Integer containing the current y location used to grow dynamic depending on the content.
int y=50;
//Now process the prompt.
{
//Pointer to the string.
char* lps=(char*)prompt.c_str();
//Pointer to a character.
char* lp=NULL;
//We keep looping forever.
//The only way out is with the break statement.
for(;;){
//As long as it's still the same sentence we continue.
//It will stop when there's a newline or end of line.
for(lp=lps;*lp!='\n'&&*lp!='\r'&&*lp!=0;lp++);
//Store the character we stopped on. (End or newline)
char c=*lp;
//Set the character in the string to 0, making lps a string containing one sentence.
*lp=0;
//Integer used to center the sentence horizontally.
int x;
TTF_SizeText(fontText,lps,&x,NULL);
x=(600-x)/2;
//Add a GUIObjectLabel with the sentence.
GUIObjectRoot->childControls.push_back(new GUIObject(x,y,584,25,GUIObjectLabel,lps));
//Increase y with 25, about the height of the text.
y+=25;
//Check the stored character if it was a stop.
if(c==0){
//It was so break out of the for loop.
lps=lp;
break;
}
//It wasn't meaning more will follow.
//We set lps to point after the "newline" forming a new string.
lps=lp+1;
}
}
//Add 70 to y to leave some space between the content and the buttons.
y+=70;
//Recalc the size of the message box.
GUIObjectRoot->top=(SCREEN_HEIGHT-y)/2;
GUIObjectRoot->height=y;
//Now we need to add the buttons.
//Integer containing the number of buttons to add.
int count=0;
//Array with the return codes for the buttons.
int value[3]={0};
//Array containing the captation for the buttons.
string button[3]={"","",""};
switch(buttons){
case MsgBoxOKCancel:
count=2;
button[0]="OK";value[0]=MsgBoxOK;
button[1]="Cancel";value[1]=MsgBoxCancel;
break;
case MsgBoxAbortRetryIgnore:
count=3;
button[0]="Abort";value[0]=MsgBoxAbort;
button[1]="Retry";value[1]=MsgBoxRetry;
button[2]="Ignore";value[2]=MsgBoxIgnore;
break;
case MsgBoxYesNoCancel:
count=3;
button[0]="Yes";value[0]=MsgBoxYes;
button[1]="No";value[1]=MsgBoxNo;
button[2]="Cancel";value[2]=MsgBoxCancel;
break;
case MsgBoxYesNo:
count=2;
button[0]="Yes";value[0]=MsgBoxYes;
button[1]="No";value[1]=MsgBoxNo;
break;
case MsgBoxRetryCancel:
count=2;
button[0]="Retry";value[0]=MsgBoxRetry;
button[1]="Cancel";value[1]=MsgBoxCancel;
break;
default:
count=1;
button[0]="OK";value[0]=MsgBoxOK;
break;
}
//Now we start making the buttons.
{
//Calculate the x location (centered).
int x=302-count*50;
//Reduce y so that the buttons fit inside the frame.
y-=40;
//Loop to add the buttons.
for(int i=0;i<count;i++,x+=100){
obj=new GUIObject(x,y,96,36,GUIObjectButton,button[i].c_str(),value[i]);
obj->eventCallback=&objHandler;
GUIObjectRoot->childControls.push_back(obj);
}
}
//Now we dim the screen and keep the GUI rendering/updating.
SDL_FillRect(tempSurface,NULL,0);
SDL_SetAlpha(tempSurface,SDL_SRCALPHA,155);
SDL_BlitSurface(tempSurface,NULL,screen,NULL);
while(GUIObjectRoot){
while(SDL_PollEvent(&event)){
GUIObjectHandleEvents(true);
//Also check for the return, escape or backspace button.
//escape = KEYUP.
//backspace and return = KEYDOWN.
if(count==1 && ((event.type==SDL_KEYUP && event.key.keysym.sym==SDLK_ESCAPE) ||
(event.type==SDL_KEYDOWN && (event.key.keysym.sym==SDLK_RETURN || event.key.keysym.sym==SDLK_BACKSPACE)))){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
//Render the gui.
if(GUIObjectRoot)
GUIObjectRoot->render();
SDL_Flip(screen);
SDL_Delay(30);
}
//We're done so set the original GUIObjectRoot back.
GUIObjectRoot=tmp;
//And return the result.
return (msgBoxResult)objHandler.ret;
}
struct fileDialogHandler:public GUIEventCallback{
public:
//The ret(urn) value, true=ok and false=cancel
bool ret;
//Boolean if it's a save dialog.
bool isSave;
//Boolean if the file should be verified.
bool verifyFile;
//Boolean if files should be listed instead of directories.
bool files;
//Pointer to the textfield containing the filename.
GUIObject* txtName;
//Pointer to the listbox containing the different files.
GUIListBox* lstFile;
//The extension the files listed should have.
const char* extension;
//The current filename.
string fileName;
//The current search path.
string path;
//Vector containing the search paths.
vector<string> searchPath;
public:
//Constructor.
fileDialogHandler(bool isSave=false,bool verifyFile=false, bool files=true):ret(false),
isSave(isSave),verifyFile(verifyFile),
files(files),txtName(NULL){}
void GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
//Check for the ok event.
if(name=="cmdOK"){
//Get the entered fileName from the text field.
std::string s=txtName->caption;
//If it doesn't contain a slash we need to add the path to the fileName.
if(s.find_first_of("/")==string::npos)
s=path+s;
//If the string empty we return.
if(s.empty() || s.find_first_of("*?")!=string::npos)
return;
//We only need to check for extensions if it isn't a folder dialog.
if(files){
//If there isn't right extension add it.
size_t found=s.find_first_of(".");
if(found!=string::npos)
s.replace(s.begin()+found+1,s.end(),extension);
else if (s.substr(found+1)!=extension)
s.append(string(".")+extension);
}
//Check if we should save or load the file.
//
if(isSave){
//Open the file with readpremission to check if it already exists.
FILE* f;
f=fopen(processFileName(s).c_str(),"rb");
//Check if it exists.
if(f){
//Close the file.
fclose(f);
//Let the currentState render once to prevent multiple GUI overlapping and prevent the screen from going black.
currentState->render();
//Prompt the user with a Yes or No question.
if(msgBox(s+" already exists.\nDo you want to overwrite it?",MsgBoxYesNo,"Overwrite Prompt")!=MsgBoxYes){
//He answered no, so we return.
return;
}
}
//Check if we should verify the file.
//Verifying only applies to files not to directories.
if(verifyFile && files){
//Open the file with write permission.
f=fopen(processFileName(s).c_str(),"wb");
//Check if their aren't problems.
if(f){
//Close the file.
fclose(f);
}else{
//Let the currentState render once to prevent multiple GUI overlapping and prevent the screen from going black.
currentState->render();
//The file can't be opened so tell the user.
msgBox("Can't open file "+s+".",MsgBoxOKOnly,"Error");
return;
}
}
}else if(verifyFile && files){
//We need to verify a file for opening.
FILE *f;
f=fopen(processFileName(s).c_str(),"rb");
//Check if it didn't fail.
if(f){
//Succes, so close the file.
fclose(f);
}else{
//Let the currentState render once to prevent multiple GUI overlapping and prevent the screen from going black.
currentState->render();
//Unable to open file so tell the user.
msgBox("Can't open file "+s+".",MsgBoxOKOnly,"Error");
return;
}
}
//If we haven't returned then it's fine.
//Set the fileName to the chosen file.
fileName=s;
//Delete the GUI.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Set return to true.
ret=true;
}else if(name=="cmdCancel"){
//Cancel means we can kill the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}else if(name=="lstFile"){
//Get a pointer to the listbox.
GUIListBox* obj1=lstFile;
//Make sure the option exist and change textfield to it.
if(obj1!=NULL && txtName!=NULL && obj1->value>=0 && obj1->value<(int)obj1->item.size()){
txtName->caption=obj1->item[obj1->value];
}
}else if(name=="lstSearchIn"){
//Get the searchpath listbox.
GUISingleLineListBox *obj1=dynamic_cast<GUISingleLineListBox*>(obj);
//Check if the entry exists.
if(obj1!=NULL && lstFile!=NULL && obj1->value>=0 && obj1->value<(int)searchPath.size()){
//Temp string.
string s;
//Get the new search path.
path=searchPath[obj1->value];
//Make sure it isn't empty.
if(!path.empty()){
//Process the filename.
s=processFileName(path);
}else{
//It's empty so we give the userpath.
s=getUserPath();
}
//Fill the list with files or directories.
if(files) {
lstFile->item=enumAllFiles(s,extension);
}else
lstFile->item=enumAllDirs(s);
//Remove any selection from the list.
lstFile->value=-1;
}
}
}
};
bool fileDialog(string& fileName,const char* title,const char* extension,const char* path,bool isSave,bool verifyFile,bool files){
//Pointer to GUIObject to make the GUI with.
GUIObject* obj;
//Pointer to the current GUIObjectRoot.
//We keep it so we can put it back after closing the fileDialog.
GUIObject* tmp=GUIObjectRoot;
//Create the fileDialogHandler, used for event handling.
fileDialogHandler objHandler(isSave,verifyFile,files);
//Vector containing the pathNames.
vector<string> pathNames;
//Set the extension of the objHandler.
objHandler.extension=extension;
//We now need to splits the given path into multiple path names.
if(path && path[0]){
//The string isn't empty.
//Pointer to the paths string.
char* lp=(char*)path;
//Pointer to the first newline.
char* lps=strchr(lp,'\n');
//Pointer used for checking if their's another newline.
//It will indicate if it's the last set or not.
char* lpe;
//Check for a newline.
if(lps){
//We have newline(s) so loop forever.
//We can only break out of the loop when the string ends.
for(;;){
//Add the first searchpath.
//This is the beginning of the string (lp) to the first newline. (lps)
objHandler.searchPath.push_back(string(lp,lps-lp));
//We should have another newline so search for it.
lpe=strchr(lps+1,'\n');
if(lpe){
//We found it so we add that to the pathname.
pathNames.push_back(string(lps+1,lpe-lps-1));
//And start over again by setting lp to the start of a new set of searchPath/pathName.
lp=lpe+1;
}else{
//There is no newline anymore, meaning the last entry, the rest of the string must be the pathName.
pathNames.push_back(string(lps+1));
//And break out of the loop.
break;
}
//We haven't broken out so search for a newline.
lps=strchr(lp,'\n');
//If there isn't a newline break.
if(!lps)
break;
}
}else{
//There is no newline thus the whole string is the searchPath.
objHandler.searchPath.push_back(path);
}
}else{
//Empty so put an empty string as searchPath.
objHandler.searchPath.push_back(string());
}
//It's time to create the GUI.
//If there are more than one pathNames we need to add a GUISingleLineListBox.
int base_y=pathNames.size()>0?60:20;
//Create the frame.
GUIObjectRoot=new GUIObject(100,100-base_y/2,600,400+base_y,GUIObjectFrame,title?title:(isSave?"Save File":"Load File"));
//Create the search path list box if needed.
if(pathNames.size()>0){
GUIObjectRoot->childControls.push_back(new GUIObject(8,40,184,36,GUIObjectLabel,"Search In"));
GUISingleLineListBox* obj1=new GUISingleLineListBox(160,40,432,36);
obj1->item=pathNames;
obj1->value=0;
obj1->name="lstSearchIn";
obj1->eventCallback=&objHandler;
GUIObjectRoot->childControls.push_back(obj1);
}
//Add the FileName label and textfield.
GUIObjectRoot->childControls.push_back(new GUIObject(8,20+base_y,184,36,GUIObjectLabel,"File Name"));
{
//Fill the textbox with the given fileName.
string s=fileName;
if(!isSave){
//But only if it isn't empty.
if(s.empty() && extension && extension[0])
s=string("*.")+string(extension);
}
//Create the textbox and add it to the GUI.
objHandler.txtName=new GUIObject(160,20+base_y,432,36,GUIObjectTextBox,s.c_str());
GUIObjectRoot->childControls.push_back(objHandler.txtName);
}
//Now we add the ListBox containing the files or directories.
{
GUIListBox* obj1=new GUIListBox(8,60+base_y,584,292);
//Get the searchPath.
string s=objHandler.searchPath[0];
//Make sure it isn't empty.
if(!s.empty()){
objHandler.path=s;
s=processFileName(s);
}else{
s=getUserPath();
}
//Check if we should list files or directories.
if(files){
//Fill the list with files.
obj1->item=enumAllFiles(s,extension);
}else{
//Fill the list with directories.
obj1->item=enumAllDirs(s);
}
obj1->name="lstFile";
obj1->eventCallback=&objHandler;
GUIObjectRoot->childControls.push_back(obj1);
objHandler.lstFile=obj1;
}
//Now create the OK and Cancel buttons.
obj=new GUIObject(200,360+base_y,192,36,GUIObjectButton,"OK");
obj->name="cmdOK";
obj->eventCallback=&objHandler;
GUIObjectRoot->childControls.push_back(obj);
obj=new GUIObject(400,360+base_y,192,36,GUIObjectButton,"Cancel");
obj->name="cmdCancel";
obj->eventCallback=&objHandler;
GUIObjectRoot->childControls.push_back(obj);
//Now we keep rendering and updating the GUI.
SDL_FillRect(tempSurface,NULL,0);
SDL_SetAlpha(tempSurface,SDL_SRCALPHA,155);
SDL_BlitSurface(tempSurface,NULL,screen,NULL);
while(GUIObjectRoot){
while(SDL_PollEvent(&event))
GUIObjectHandleEvents(true);
if(GUIObjectRoot)
GUIObjectRoot->render();
SDL_Flip(screen);
SDL_Delay(30);
}
//The while loop ended meaning we can restore the previous GUI.
GUIObjectRoot=tmp;
//Now determine what the return value is (and if there is one).
if(objHandler.ret)
fileName=objHandler.fileName;
return objHandler.ret;
}
diff --git a/src/LevelSelect.cpp b/src/LevelSelect.cpp
index b6514d9..f4673aa 100644
--- a/src/LevelSelect.cpp
+++ b/src/LevelSelect.cpp
@@ -1,697 +1,697 @@
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "GameState.h"
#include "Functions.h"
#include "FileManager.h"
#include "Globals.h"
#include "Objects.h"
#include "LevelSelect.h"
#include "GUIObject.h"
#include "GUIListBox.h"
#include "GUIScrollBar.h"
#include "InputManager.h"
#include "Game.h"
#include <SDL/SDL_ttf.h>
#include <SDL/SDL.h>
#include <stdio.h>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
static SDL_Surface* playButtonImage=NULL;
////////////////////NUMBER////////////////////////
Number::Number(){
image=NULL;
background=NULL;
number=0;
medal=0;
selected=false;
//Set the default dimensions.
box.x=0;
box.y=0;
box.h=50;
box.w=50;
//Load the medals image.
medals=loadImage(getDataPath()+"gfx/medals.png");
}
Number::~Number(){
//We only need to free the SDLSurface.
if(image) SDL_FreeSurface(image);
}
void Number::init(int number,SDL_Rect box){
//First set the number and update our status.
this->number=number;
update();
//Write our text, number+1 since the counting doens't start with 0, but with 1.
std::stringstream text;
number++;
text<<number;
//Create the text image.
SDL_Color black={0,0,0};
if(image) SDL_FreeSurface(image);
//Create the text image.
//Also check which font to use, if the number is higher than 100 use the small font.
image=TTF_RenderText_Blended(fontGUI,text.str().c_str(),black);
//Set the new location of the number.
this->box.x=box.x;
this->box.y=box.y;
}
void Number::show(int dy){
//First draw the background, also apply the yOffset(dy).
applySurface(box.x,box.y-dy,background,screen,NULL);
//Now draw the text image over the background.
//We draw it centered inside the box.
applySurface((box.x+25-(image->w/2)),box.y+((TTF_FontAscent(fontGUI)+TTF_FontDescent(fontGUI))/2)-dy,image,screen,NULL);
//Draw the selection mark.
if(selected){
- drawGUIBox(box.x,box.y-dy,50,50,screen,0x00000000);
+ drawGUIBox(box.x,box.y-dy,50,50,screen,0xFFFFFF23);
}
//Draw the medal.
if(medal>0){
SDL_Rect r={(medal-1)*30,0,30,30};
applySurface(box.x+30,(box.y+30)-dy,medals,screen,&r);
}
}
void Number::update(){
//Check if the level is locked, if so change the background to the locked image.
if(levels.getLocked(number)==false){
background=loadImage(getDataPath()+"gfx/level.png");
}else{
background=loadImage(getDataPath()+"gfx/levellocked.png");
}
//Set the medal.
medal=levels.getLevel(number)->won;
if(medal){
if(levels.getLevel(number)->targetTime<0 || levels.getLevel(number)->time<=levels.getLevel(number)->targetTime)
medal++;
if(levels.getLevel(number)->targetRecordings<0 || levels.getLevel(number)->recordings<=levels.getLevel(number)->targetRecordings)
medal++;
}
}
/////////////////////LEVEL SELECT/////////////////////
static GUIScrollBar* levelScrollBar=NULL;
static GUIObject* levelpackDescription=NULL;
static string levelDescription,levelMedal,levelMedal2,levelMedal3;
static string bestTimeFilePath,bestRecordingFilePath;
LevelSelect::LevelSelect(){
//clear the selected level
selectedNumber=NULL;
//Set the play button to NULL.
play=NULL;
//Load the background image.
background=loadImage(getDataPath()+"gfx/menu/background.png");
if(playButtonImage==NULL){
playButtonImage=loadImage(getDataPath()+"gfx/playbutton.png");
}
//Render the title.
SDL_Color black={0,0,0};
title=TTF_RenderText_Blended(fontTitle,"Select Level",black);
//create GUI (test only)
GUIObject* obj;
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
GUIObjectRoot=new GUIObject(0,0,800,600);
//the level select scroll bar
levelScrollBar=new GUIScrollBar(768,184,16,242,ScrollBarVertical,0,0,0,1,4,true,false);
GUIObjectRoot->childControls.push_back(levelScrollBar);
//level pack description
levelpackDescription=new GUIObject(60,140,800,32,GUIObjectLabel);
GUIObjectRoot->childControls.push_back(levelpackDescription);
GUISingleLineListBox* levelpacks=new GUISingleLineListBox(150,104,500,32);
levelpacks->name="cmdLvlPack";
levelpacks->eventCallback=this;
vector<string> v=enumAllDirs(getDataPath()+"levelpacks/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levelpackLocations[*i]=getDataPath()+"levelpacks/"+*i;
}
vector<string> v2=enumAllDirs(getUserPath()+"levelpacks/");
for(vector<string>::iterator i=v2.begin(); i!=v2.end(); ++i){
levelpackLocations[*i]=getUserPath()+"levelpacks/"+*i;
}
vector<string> v3=enumAllDirs(getUserPath()+"custom/levelpacks/");
for(vector<string>::iterator i=v3.begin(); i!=v3.end(); ++i){
levelpackLocations[*i]=getUserPath()+"custom/levelpacks/"+*i;
}
v.insert(v.end(),v2.begin(),v2.end());
v.insert(v.end(),v3.begin(),v3.end());
//Now we add a special levelpack that will contain the levels not in a levelpack.
v.push_back("Levels");
levelpacks->item=v;
levelpacks->value=0;
//Check if we can find the lastlevelpack.
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
if(*i==getSettings()->getValue("lastlevelpack")){
levelpacks->value=i-v.begin();
string s1=getUserPath()+"progress/"+*i+".progress";
//Check if this is the special Levels levelpack.
if(*i=="Levels"){
//Clear the current levels.
levels.clear();
levels.setCurrentLevel(0);
//List the custom levels and add them one for one.
vector<string> v=enumAllFiles(getUserPath()+"custom/levels/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levels.addLevel(getUserPath()+"custom/levels/"+*i);
levels.setLocked(levels.getLevelCount()-1);
}
//List the addon levels and add them one for one.
v=enumAllFiles(getUserPath()+"levels/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levels.addLevel(getUserPath()+"levels/"+*i);
levels.setLocked(levels.getLevelCount()-1);
}
}else{
//This isn't so load the levelpack in the normal way.
if(!levels.loadLevels(levelpackLocations[*i]+"/levels.lst")){
msgBox("Can't load level pack:\n"+*i,MsgBoxOKOnly,"Error");
}
}
//Load the progress.
levels.loadProgress(s1);
}
}
GUIObjectRoot->childControls.push_back(levelpacks);
obj=new GUIObject(20,540,240,32,GUIObjectButton,"Back");
obj->name="cmdBack";
obj->eventCallback=this;
GUIObjectRoot->childControls.push_back(obj);
play=new GUIObject(560,540,240,32,GUIObjectButton,"Play");
play->name="cmdPlay";
play->eventCallback=this;
play->visible=false;
GUIObjectRoot->childControls.push_back(play);
//show level list
refresh();
}
void LevelSelect::refresh(){
int m=levels.getLevelCount();
numbers.clear();
//clear the selected level
if(selectedNumber!=NULL){
delete selectedNumber;
selectedNumber=NULL;
}
//Hide the play button.
play->visible=false;
for(int n=0; n<m; n++){
numbers.push_back(Number());
}
for(int n=0; n<m; n++){
SDL_Rect box={(n%10)*64+80,(n/10)*64+184,0,0};
numbers[n].init(n,box);
}
if(m>40){
levelScrollBar->maxValue=(m-41)/10;
levelScrollBar->visible=true;
}else{
levelScrollBar->maxValue=0;
levelScrollBar->visible=false;
}
levelpackDescription->caption=levels.levelpackDescription;
int width,height;
TTF_SizeText(fontGUI,levels.levelpackDescription.c_str(),&width,&height);
levelpackDescription->left=(800-width)/2;
}
LevelSelect::~LevelSelect(){
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
play=NULL;
levelScrollBar=NULL;
levelpackDescription=NULL;
if(selectedNumber!=NULL)
delete selectedNumber;
//Free the rendered title surface.
SDL_FreeSurface(title);
}
void LevelSelect::handleEvents(){
//Check for an SDL_QUIT event.
if(event.type==SDL_QUIT){
setNextState(STATE_EXIT);
}
//Check for a mouse click.
if(event.type==SDL_MOUSEBUTTONUP && event.button.button==SDL_BUTTON_LEFT){
checkMouse();
}
//Check if escape is pressed.
if(inputMgr.isKeyUpEvent(INPUTMGR_ESCAPE)){
setNextState(STATE_MENU);
}
//Check for scrolling down and up.
if(event.type==SDL_MOUSEBUTTONDOWN && event.button.button==SDL_BUTTON_WHEELDOWN && levelScrollBar){
if(levelScrollBar->value<levelScrollBar->maxValue) levelScrollBar->value++;
return;
}else if(event.type==SDL_MOUSEBUTTONDOWN && event.button.button==SDL_BUTTON_WHEELUP && levelScrollBar){
if(levelScrollBar->value>0) levelScrollBar->value--;
return;
}
}
void LevelSelect::checkMouse(){
int x,y,dy=0,m=levels.getLevelCount();
//Get the current mouse location.
SDL_GetMouseState(&x,&y);
//Check if we should replay the record.
if(selectedNumber!=NULL){
SDL_Rect mouse={x,y,0,0};
if(!bestTimeFilePath.empty()){
SDL_Rect box={380,440,372,32};
if(checkCollision(box,mouse)){
Game::recordFile=bestTimeFilePath;
levels.setCurrentLevel(selectedNumber->getNumber());
setNextState(STATE_GAME);
//Pick music from the current music list.
getMusicManager()->pickMusic();
return;
}
}
if(!bestRecordingFilePath.empty()){
SDL_Rect box={380,472,372,32};
if(checkCollision(box,mouse)){
Game::recordFile=bestRecordingFilePath;
levels.setCurrentLevel(selectedNumber->getNumber());
setNextState(STATE_GAME);
//Pick music from the current music list.
getMusicManager()->pickMusic();
return;
}
}
}
//Check if there's a scrollbar, if so get the value.
if(levelScrollBar)
dy=levelScrollBar->value;
if(m>dy*10+50)
m=dy*10+50;
y+=dy*64;
SDL_Rect mouse={x,y,0,0};
for(int n=dy*10; n<m; n++){
if(levels.getLocked(n)==false){
if(checkCollision(mouse,numbers[n].box)==true){
if(numbers[n].selected){
//Current level was selected, so play it
levels.setCurrentLevel(n);
setNextState(STATE_GAME);
//Pick music from the current music list.
getMusicManager()->pickMusic();
}else{
//Select current level
for(int i=0;i<levels.getLevelCount();i++){
numbers[i].selected=(i==n);
}
//Display level info
displayLevelInfo(n);
}
break;
}
}
}
}
void LevelSelect::displayLevelInfo(int number){
//Update currently selected level
if(selectedNumber==NULL){
selectedNumber=new Number();
}
SDL_Rect box={40,440,50,50};
selectedNumber->init(number,box);
//Show level description
levelDescription=levels.getLevelName(number);
//Show level medal
int medal=levels.getLevel(number)->won;
int time=levels.getLevel(number)->time;
int targetTime=levels.getLevel(number)->targetTime;
int recordings=levels.getLevel(number)->recordings;
int targetRecordings=levels.getLevel(number)->targetRecordings;
if(medal){
if(targetTime<0 && targetTime<0){
medal=-1;
}else{
if(targetTime<0 || time<=targetTime)
medal++;
if(targetRecordings<0 || recordings<=targetRecordings)
medal++;
}
}
switch(medal){
case 0:
levelMedal="You haven't finished this level ";//"Medal: None";
break;
case 1:
levelMedal="Medal: Bronze";
break;
case 2:
levelMedal="Medal: Silver";
break;
case 3:
levelMedal="Medal: Gold";
break;
default:
levelMedal="Medal: Not avaliable for this level";
break;
}
//Show best time and recordings
if(medal){
char s[64];
if(time>0)
if(targetTime>0)
sprintf(s,"%-.2fs / %-.2fs",time/40.0f,targetTime/40.0f);
else
sprintf(s,"%-.2fs",time/40.0f);
else
s[0]='\0';
levelMedal2=string("Time: ")+s;
if(recordings>=0)
if(targetRecordings>=0)
sprintf(s,"%5d / %d",recordings,targetRecordings);
else
sprintf(s,"%d",recordings);
else
s[0]='\0';
levelMedal3=string("Recordings: ")+s;
}else{
levelMedal2.clear();
levelMedal3.clear();
}
//Show the play button.
play->visible=true;
//Check if there is auto record file
levels.getLevelAutoSaveRecordPath(number,bestTimeFilePath,bestRecordingFilePath,false);
if(!bestTimeFilePath.empty()){
FILE *f;
f=fopen(bestTimeFilePath.c_str(),"rb");
if(f==NULL){
bestTimeFilePath.clear();
}else{
fclose(f);
}
}
if(!bestRecordingFilePath.empty()){
FILE *f;
f=fopen(bestRecordingFilePath.c_str(),"rb");
if(f==NULL){
bestRecordingFilePath.clear();
}else{
fclose(f);
}
}
}
void LevelSelect::logic(){}
void LevelSelect::render(){
int x,y,dy=0,m=levels.getLevelCount();
int idx=-1;
//Get the current mouse location.
SDL_GetMouseState(&x,&y);
if(levelScrollBar)
dy=levelScrollBar->value;
if(m>dy*10+40)
m=dy*10+40;
y+=dy*64;
SDL_Rect mouse={x,y,0,0};
//Draw the background.
applySurface(0,0,background,screen,NULL);
//Draw the title.
applySurface((800-title->w)/2,40,title,screen,NULL);
//Loop through the level blocks and draw them.
for(int n=dy*10; n<m;n++){
numbers[n].show(dy*64);
if(levels.getLocked(n)==false && checkCollision(mouse,numbers[n].box)==true)
idx=n;
}
//Show currently selected level (if any)
if(selectedNumber!=NULL){
//Draw a background for the stats.
drawGUIBox(0,420,SCREEN_WIDTH,SCREEN_HEIGHT-420,screen,0xFFFFFF80);
selectedNumber->show(0);
SDL_Color fg={0,0,0};
SDL_Surface* bm;
if(!levelDescription.empty()){
bm=TTF_RenderText_Blended(fontText,levelDescription.c_str(),fg);
applySurface(100,440,bm,screen,NULL);
SDL_FreeSurface(bm);
}
if(!levelMedal.empty()){
bm=TTF_RenderText_Blended(fontText,levelMedal.c_str(),fg);
applySurface(40,504,bm,screen,NULL);
SDL_FreeSurface(bm);
}
//Only show the replay if the level is completed (won).
if(levels.getLevel(selectedNumber->getNumber())->won){
if(!bestTimeFilePath.empty()){
SDL_Rect r={0,0,32,32};
SDL_Rect box={380,440,372,32};
if(checkCollision(box,mouse)){
r.x=32;
SDL_FillRect(screen,&box,0xFFCCCCCC);
}
applySurface(720,440,playButtonImage,screen,&r);
}
if(!bestRecordingFilePath.empty()){
SDL_Rect r={0,0,32,32};
SDL_Rect box={380,472,372,32};
if(checkCollision(box,mouse)){
r.x=32;
SDL_FillRect(screen,&box,0xFFCCCCCC);
}
applySurface(720,472,playButtonImage,screen,&r);
}
}
if(!levelMedal2.empty()){
bm=TTF_RenderText_Blended(fontText,levelMedal2.c_str(),fg);
applySurface(380,440+(32-bm->h)/2,bm,screen,NULL);
SDL_FreeSurface(bm);
}
if(!levelMedal3.empty()){
bm=TTF_RenderText_Blended(fontText,levelMedal3.c_str(),fg);
applySurface(380,472+(32-bm->h)/2,bm,screen,NULL);
SDL_FreeSurface(bm);
}
}
//Show the tool tip text.
if(idx>=0){
SDL_Color fg={0,0,0};
char s[64];
//Render the name of the level.
SDL_Surface* name=TTF_RenderText_Blended(fontText,levels.getLevelName(idx).c_str(),fg);
SDL_Surface* time=NULL;
SDL_Surface* recordings=NULL;
//The time it took.
if(levels.getLevel(idx)->time>0){
sprintf(s,"%-.2fs",levels.getLevel(idx)->time/40.0f);
time=TTF_RenderText_Blended(fontText,(string("Time: ")+s).c_str(),fg);
}
//The number of recordings it took.
if(levels.getLevel(idx)->recordings>=0){
sprintf(s,"%d",levels.getLevel(idx)->recordings);
recordings=TTF_RenderText_Blended(fontText,(string("Recordings: ")+s).c_str(),fg);
}
//Now draw a square the size of the three texts combined.
SDL_Rect r=numbers[idx].box;
r.y-=dy*80;
if(time!=NULL && recordings!=NULL){
r.w=(name->w)>time->w?(name->w)>recordings->w?name->w:recordings->w:(time->w)>recordings->w?time->w:recordings->w;
r.h=name->h+5+time->h+recordings->h;
}else{
r.w=name->w;
r.h=name->h;
}
//Make sure the tooltip doesn't go outside the window.
if(r.y>SCREEN_HEIGHT-200){
r.y-=name->h+4;
}else{
r.y+=numbers[idx].box.h+2;
}
if(r.x+r.w>SCREEN_WIDTH-50)
r.x=SCREEN_WIDTH-50-r.w;
//Draw a rectange
Uint32 color=0xFFFFFF00|240;
drawGUIBox(r.x-5,r.y-5,r.w+10,r.h+10,screen,color);
//Calc the position to draw.
SDL_Rect r2=r;
//Now we render the name if the surface isn't null.
if(name!=NULL){
//Draw the name.
SDL_BlitSurface(name,NULL,screen,&r2);
}
//Increase the height to leave a gap between name and stats.
r2.y+=5;
if(time!=NULL){
//Now draw the time.
r2.y+=name->h;
SDL_BlitSurface(time,NULL,screen,&r2);
}
if(recordings!=NULL){
//Now draw the recordings.
r2.y+=time->h;
SDL_BlitSurface(recordings,NULL,screen,&r2);
}
//And free the surfaces.
SDL_FreeSurface(name);
SDL_FreeSurface(time);
SDL_FreeSurface(recordings);
}
}
void LevelSelect::GUIEventCallback_OnEvent(std::string Name,GUIObject* obj,int nEventType){
string s;
if(Name=="cmdLvlPack"){
s=levelpackLocations[((GUISingleLineListBox*)obj)->item[obj->value]];
getSettings()->setValue("lastlevelpack",((GUISingleLineListBox*)obj)->item[obj->value]);
}else if(Name=="cmdBack"){
setNextState(STATE_MENU);
return;
}else if(Name=="cmdPlay"){
if(selectedNumber!=NULL){
levels.setCurrentLevel(selectedNumber->getNumber());
setNextState(STATE_GAME);
//Pick music from the current music list.
getMusicManager()->pickMusic();
}
return;
}else{
return;
}
string s1=getUserPath()+"progress/"+((GUISingleLineListBox*)obj)->item[obj->value]+".progress";
//Check if this is the special Levels levelpack.
if(((GUISingleLineListBox*)obj)->item[obj->value]=="Levels"){
//Clear the current levels.
levels.clear();
levels.setCurrentLevel(0);
//List the custom levels and add them one for one.
vector<string> v=enumAllFiles(getUserPath()+"custom/levels/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levels.addLevel(getUserPath()+"custom/levels/"+*i);
levels.setLocked(levels.getLevelCount()-1);
}
//List the addon levels and add them one for one.
v=enumAllFiles(getUserPath()+"levels/");
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
levels.addLevel(getUserPath()+"levels/"+*i);
levels.setLocked(levels.getLevelCount()-1);
}
}else{
//This isn't so load the levelpack in the normal way.
if(!levels.loadLevels(levelpackLocations[((GUISingleLineListBox*)obj)->item[obj->value]]+"/levels.lst")){
msgBox("Can't load level pack:\n"+((GUISingleLineListBox*)obj)->item[obj->value],MsgBoxOKOnly,"Error");
}
}
//Load the progress file.
levels.loadProgress(s1);
//And refresh the numbers.
refresh();
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 18, 8:19 PM (1 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
72992
Default Alt Text
(48 KB)

Event Timeline