From: Ingo Ruhnke Date: Wed, 16 Jun 2004 00:40:42 +0000 (+0000) Subject: - moved level subsets into their own file X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=7dd997b1207127e88f42915ec8bc1aa8e7599ad1;p=supertux.git - moved level subsets into their own file - changed level subsets so that they do a readdir() instead of iterating ovre level1, level2,.. until error, this should also allow abitary level file names SVN-Revision: 1502 --- diff --git a/src/Makefile.am b/src/Makefile.am index 6fc28fdb9..c6c9bef04 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,6 +44,8 @@ interactive_object.cpp \ interactive_object.h \ level.cpp \ level.h \ +level_subset.cpp \ +level_subset.h \ leveleditor.cpp \ leveleditor.h \ lispreader.cpp \ diff --git a/src/level.cpp b/src/level.cpp index b2748d9ef..3470547e7 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -42,185 +42,6 @@ using namespace std; -LevelSubset::LevelSubset() - : image(0), levels(0) -{ -} - -LevelSubset::~LevelSubset() -{ - delete image; -} - -void LevelSubset::create(const std::string& subset_name) -{ - Level new_lev; - LevelSubset new_subset; - new_subset.name = subset_name; - new_subset.title = "Unknown Title"; - new_subset.description = "No description so far."; - new_subset.save(); - //new_lev.save(subset_name, 1, 0); -} - -void LevelSubset::parse (lisp_object_t* cursor) -{ - while(!lisp_nil_p(cursor)) - { - lisp_object_t* cur = lisp_car(cursor); - char *s; - - if (!lisp_cons_p(cur) || !lisp_symbol_p (lisp_car(cur))) - { - printf("Not good"); - } - else - { - if (strcmp(lisp_symbol(lisp_car(cur)), "title") == 0) - { - if(( s = lisp_string(lisp_car(lisp_cdr(cur)))) != NULL) - { - title = s; - } - } - else if (strcmp(lisp_symbol(lisp_car(cur)), "description") == 0) - { - if(( s = lisp_string(lisp_car(lisp_cdr(cur)))) != NULL) - { - description = s; - } - } - } - cursor = lisp_cdr (cursor); - } -} - -void LevelSubset::load(const char* subset) -{ - FILE* fi; - char filename[1024]; - char str[1024]; - int i; - lisp_object_t* root_obj = 0; - - name = subset; - - snprintf(filename, 1024, "%s/levels/%s/info", st_dir, subset); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/info", datadir.c_str(), subset); - if(faccessible(filename)) - { - fi = fopen(filename, "r"); - if (fi == NULL) - { - perror(filename); - } - lisp_stream_t stream; - lisp_stream_init_file (&stream, fi); - root_obj = lisp_read (&stream); - - if (root_obj->type == LISP_TYPE_EOF || root_obj->type == LISP_TYPE_PARSE_ERROR) - { - printf("World: Parse Error in file %s", filename); - } - - lisp_object_t* cur = lisp_car(root_obj); - - if (!lisp_symbol_p (cur)) - { - printf("World: Read error in %s",filename); - } - - if (strcmp(lisp_symbol(cur), "supertux-level-subset") == 0) - { - parse(lisp_cdr(root_obj)); - - } - - lisp_free(root_obj); - fclose(fi); - - snprintf(str, 1024, "%s.png", filename); - if(faccessible(str)) - { - delete image; - image = new Surface(str,IGNORE_ALPHA); - } - else - { - snprintf(filename, 1024, "%s/images/status/level-subset-info.png", datadir.c_str()); - delete image; - image = new Surface(filename,IGNORE_ALPHA); - } - } - - for(i=1; i != -1; ++i) - { - /* Get the number of levels in this subset */ - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, subset,i); - if(!faccessible(filename)) - { - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), subset,i); - if(!faccessible(filename)) - break; - } - } - levels = --i; -} - -void -LevelSubset::save() -{ - FILE* fi; - string filename; - - /* Save data file: */ - filename = "/levels/" + name + "/"; - - fcreatedir(filename.c_str()); - filename = string(st_dir) + "/levels/" + name + "/info"; - if(!fwriteable(filename.c_str())) - filename = datadir + "/levels/" + name + "/info"; - if(fwriteable(filename.c_str())) - { - fi = fopen(filename.c_str(), "w"); - if (fi == NULL) - { - perror(filename.c_str()); - } - - /* Write header: */ - fprintf(fi,";SuperTux-Level-Subset\n"); - fprintf(fi,"(supertux-level-subset\n"); - - /* Save title info: */ - fprintf(fi," (title \"%s\")\n", title.c_str()); - - /* Save the description: */ - fprintf(fi," (description \"%s\")\n", description.c_str()); - - fprintf( fi,")"); - fclose(fi); - } -} - -std::string -LevelSubset::get_level_filename(unsigned int num) -{ - char filename[1024]; - - // Load data file: - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, - name.c_str(), num); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), - name.c_str(), num); - - return std::string(filename); -} - -//--------------------------------------------------------------------------- - Level::Level() : name("noname"), author("mr. x"), time_left(500) { diff --git a/src/level.h b/src/level.h index e9bb6f0d3..c955c5f2c 100644 --- a/src/level.h +++ b/src/level.h @@ -24,37 +24,8 @@ #include #include -#include "screen/surface.h" -#include "lispreader.h" -#include "musicref.h" - -class Tile; - -/** This type holds meta-information about a level-subset. - It could be extended to handle manipulation of subsets. */ -class LevelSubset -{ -public: - LevelSubset(); - ~LevelSubset(); - - static void create(const std::string& subset_name); - void load(const char* subset); - void save(); - - std::string get_level_filename(unsigned int i); - - std::string name; - std::string title; - std::string description; - Surface* image; - int levels; - -private: - void parse(lisp_object_t* cursor); -}; - class Sector; +class LispReader; class Level { diff --git a/src/level_subset.cpp b/src/level_subset.cpp index f4011211e..25785d164 100644 --- a/src/level_subset.cpp +++ b/src/level_subset.cpp @@ -18,20 +18,28 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. +#include #include "setup.h" #include "level.h" #include "globals.h" #include "screen/surface.h" #include "level_subset.h" +static bool has_suffix(const std::string& data, const std::string& suffix) +{ + if (data.length() >= suffix.length()) + return data.compare(data.length() - suffix.length(), suffix.length(), suffix) == 0; + else + return false; +} + LevelSubset::LevelSubset() - : image(0), levels(0) + : levels(0) { } LevelSubset::~LevelSubset() { - delete image; } void LevelSubset::create(const std::string& subset_name) @@ -42,112 +50,74 @@ void LevelSubset::create(const std::string& subset_name) new_subset.title = "Unknown Title"; new_subset.description = "No description so far."; new_subset.save(); - //new_lev.save(subset_name, 1, 0); } -void LevelSubset::parse (lisp_object_t* cursor) +void LevelSubset::read_info_file(const std::string& info_file) { - while(!lisp_nil_p(cursor)) + lisp_object_t* root_obj = lisp_read_from_file(info_file); + lisp_object_t* cur = lisp_car(root_obj); + + if (lisp_symbol_p(cur) && strcmp(lisp_symbol(cur), "supertux-level-subset") == 0) { - lisp_object_t* cur = lisp_car(cursor); - char *s; + LispReader reader(lisp_cdr(root_obj)); - if (!lisp_cons_p(cur) || !lisp_symbol_p (lisp_car(cur))) - { - printf("Not good"); - } - else - { - if (strcmp(lisp_symbol(lisp_car(cur)), "title") == 0) - { - if(( s = lisp_string(lisp_car(lisp_cdr(cur)))) != NULL) - { - title = s; - } - } - else if (strcmp(lisp_symbol(lisp_car(cur)), "description") == 0) - { - if(( s = lisp_string(lisp_car(lisp_cdr(cur)))) != NULL) - { - description = s; - } - } - } - cursor = lisp_cdr (cursor); + reader.read_string("title", title); + reader.read_string("description", description); + reader.read_string_vector("levels", levels); + } + else + { + std::cout << "LevelSubset: parse error in info file: " << info_file << std::endl; } + + lisp_free(root_obj); } void LevelSubset::load(const char* subset) { - FILE* fi; - char filename[1024]; - char str[1024]; - int i; - lisp_object_t* root_obj = 0; - name = subset; - - snprintf(filename, 1024, "%s/levels/%s/info", st_dir, subset); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/info", datadir.c_str(), subset); - if(faccessible(filename)) + + // Check in which directory our subset is located (ie. ~/.supertux/ + // or SUPERTUX_DATADIR) + char filename[1024]; + snprintf(filename, 1024, "%s/levels/%s/", st_dir, subset); + if (access(filename, R_OK) == 0) { - fi = fopen(filename, "r"); - if (fi == NULL) - { - perror(filename); - } - lisp_stream_t stream; - lisp_stream_init_file (&stream, fi); - root_obj = lisp_read (&stream); - - if (root_obj->type == LISP_TYPE_EOF || root_obj->type == LISP_TYPE_PARSE_ERROR) - { - printf("World: Parse Error in file %s", filename); - } - - lisp_object_t* cur = lisp_car(root_obj); - - if (!lisp_symbol_p (cur)) - { - printf("World: Read error in %s",filename); - } - - if (strcmp(lisp_symbol(cur), "supertux-level-subset") == 0) - { - parse(lisp_cdr(root_obj)); - - } - - lisp_free(root_obj); - fclose(fi); - - snprintf(str, 1024, "%s.png", filename); - if(faccessible(str)) + directory = filename; + } + else + { + snprintf(filename, 1024, "%s/levels/%s/", datadir.c_str(), subset); + if (access(filename, R_OK) == 0) + directory = filename; + else + std::cout << "Error: LevelSubset: couldn't find subset: " << subset << std::endl; + } + + read_info_file(directory + "info"); + + if (levels.empty()) + { // Level info file doesn't define any levels, so read the + // directory to see what we can find + std::vector files; + + snprintf(filename, 1024, "%s/levels/%s/", st_dir, subset); + if(access(filename, R_OK) == 0) { - delete image; - image = new Surface(str,IGNORE_ALPHA); + files = read_directory(filename); } else { - snprintf(filename, 1024, "%s/images/status/level-subset-info.png", datadir.c_str()); - delete image; - image = new Surface(filename,IGNORE_ALPHA); + snprintf(filename, 1024, "%s/levels/%s/", datadir.c_str(), subset); + files = read_directory(filename); } - } - - for(i=1; i != -1; ++i) - { - /* Get the number of levels in this subset */ - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, subset,i); - if(!faccessible(filename)) + + for(std::vector::iterator i = files.begin(); i != files.end(); ++i) { - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), subset,i); - if(!faccessible(filename)) - break; + if (has_suffix(*i, ".stl")) + levels.push_back(*i); } } - levels = --i; } void @@ -172,7 +142,7 @@ LevelSubset::save() } /* Write header: */ - fprintf(fi,";SuperTux-Level-Subset\n"); + fprintf(fi,";; SuperTux-Level-Subset\n"); fprintf(fi,"(supertux-level-subset\n"); /* Save title info: */ @@ -186,20 +156,24 @@ LevelSubset::save() } } +void +LevelSubset::add_level(const std::string& name) +{ + levels.push_back(name); +} + std::string LevelSubset::get_level_filename(unsigned int num) { - char filename[1024]; - - // Load data file: - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, - name.c_str(), num); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), - name.c_str(), num); - - return std::string(filename); + assert(num < levels.size()); + + return directory + levels[num]; } -/* EOF */ +int +LevelSubset::get_num_levels() const +{ + return levels.size(); +} +/* EOF */ diff --git a/src/level_subset.h b/src/level_subset.h index 45be7aed8..4ff6b4da9 100644 --- a/src/level_subset.h +++ b/src/level_subset.h @@ -21,6 +21,7 @@ #ifndef SUPERTUX_LEVEL_SUBSET_H #define SUPERTUX_LEVEL_SUBSET_H +#include #include #include "lispreader.h" @@ -30,6 +31,14 @@ class Surface; It could be extended to handle manipulation of subsets. */ class LevelSubset { +private: + /** Directory in which the level subset is stored */ + std::string directory; + + /** Level filenames without the leading path ("level1.stl", + "level3.stl", ...) */ + std::vector levels; + public: LevelSubset(); ~LevelSubset(); @@ -38,16 +47,18 @@ public: void load(const char* subset); void save(); + void add_level(const std::string& name); + std::string get_level_filename(unsigned int i); + int get_num_levels() const; std::string name; std::string title; std::string description; Surface* image; - int levels; - + private: - void parse(lisp_object_t* cursor); + void read_info_file(const std::string& info_file); }; #endif diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp index 6b1b9aa41..2d7f6f742 100644 --- a/src/leveleditor.cpp +++ b/src/leveleditor.cpp @@ -822,8 +822,8 @@ void LevelEditor::drawinterface(DrawingContext &context) le_object_properties_bt->draw(context); } - sprintf(str, "%d/%d", le_levelnb,le_level_subset->levels); - context.draw_text(white_text, str, Vector((le_level_subset->levels < 10) ? -10 : 0, 16), LAYER_GUI); + sprintf(str, "%d/%d", le_levelnb, le_level_subset->get_num_levels()); + context.draw_text(white_text, str, Vector((le_level_subset->get_num_levels() < 10) ? -10 : 0, 16), LAYER_GUI); if(!le_help_shown) context.draw_text(white_small_text, "F1 for Help", Vector(10, 430), LAYER_GUI); @@ -1153,7 +1153,7 @@ void LevelEditor::checkevents() le_next_level_bt->event(event); if(le_next_level_bt->get_state() == BUTTON_CLICKED) { - if(le_levelnb < le_level_subset->levels) + if(le_levelnb < le_level_subset->get_num_levels()) { goto_level(le_levelnb+1); } @@ -1165,8 +1165,8 @@ void LevelEditor::checkevents() Surface* surf = new Surface(le_level->get_sector("main")->background->get_image(), false); if(confirm_dialog(surf, str)) { - new_lev.save(le_level_subset->name.c_str()); - le_level_subset->levels = le_levelnb; + le_level_subset->add_level("newlevel.stl"); + new_lev.save(le_level_subset->get_level_filename(le_levelnb+1)); goto_level(le_levelnb); } if(surf != NULL) diff --git a/src/leveleditor.h b/src/leveleditor.h index 4ded83fbc..5c333a814 100644 --- a/src/leveleditor.h +++ b/src/leveleditor.h @@ -27,6 +27,8 @@ #include "game_object.h" #include "screen/surface.h" #include "level.h" +#include "level_subset.h" +#include "moving_object.h" #include "button.h" #include "menu.h" diff --git a/src/setup.cpp b/src/setup.cpp index 45a8bed65..4a58f76c6 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -1112,3 +1112,24 @@ void usage(char * prog, int ret) exit(ret); } +std::vector read_directory(const std::string& pathname) +{ + std::vector dirnames; + + DIR* dir = opendir(pathname.c_str()); + if (dir) + { + struct dirent *direntp; + + while((direntp = readdir(dir))) + { + dirnames.push_back(direntp->d_name); + } + + closedir(dir); + } + + return dirnames; +} + +/* EOF */ diff --git a/src/setup.h b/src/setup.h index 1661be7bc..ebb85c40e 100644 --- a/src/setup.h +++ b/src/setup.h @@ -20,6 +20,8 @@ #ifndef SUPERTUX_SETUP_H #define SUPERTUX_SETUP_H +#include +#include #include "menu.h" #include "sound.h" #include "type.h" @@ -27,6 +29,8 @@ int faccessible(const char *filename); int fcreatedir(const char* relative_dir); int fwriteable(const char *filename); +std::vector read_directory(const std::string& pathname); + FILE * opendata(const char * filename, const char * mode); string_list_type dsubdirs(const char *rel_path, const char* expected_file); string_list_type dfiles(const char *rel_path, const char* glob, const char* exception_str); diff --git a/src/title.cpp b/src/title.cpp index 7d75ef1a7..84bd3f676 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -129,7 +129,7 @@ void check_contrib_menu() contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0); contrib_subset_menu->additem(MN_HL,"",0,0); - for (int i = 1; i <= subset.levels; ++i) + for (int i = 0; i < subset.get_num_levels(); ++i) { Level* level = new Level; level->load(subset.get_level_filename(i));