From: Ricardo Cruz Date: Fri, 24 Sep 2004 15:10:10 +0000 (+0000) Subject: Uploading the level editor I was working on - It isn't still usable, but it was only... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=d5f3984577afe481c7e0596d3a01f86c8ae83945;p=supertux.git Uploading the level editor I was working on - It isn't still usable, but it was only getting dust and getting obsolete due to changes on API. Also, made the necessary changes on other stuff. Some bugs were introduced (others were already there :)). SVN-Revision: 1964 --- diff --git a/src/level.cpp b/src/level.cpp index aad2bf959..94c98b34c 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -158,6 +158,58 @@ Level::get_sector(const std::string& name) return i->second; } +const std::string& +Level::get_sector_name(const Sector* sector) +{ + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) + { + if(i->second == sector) + return i->first; + } + std::cerr << "Warning: Sector not found on level\n"; + return ""; +} + +Sector* +Level::get_next_sector(const Sector* sector) +{ + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) + { + if(i->second == sector) + { + i++; + if(i == sectors.end()) + return NULL; + return i->second; + } + } + std::cerr << "Warning: Sector not found on level\n"; + return NULL; +} + +Sector* +Level::get_previous_sector(const Sector* sector) +{ + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) + { + if(i->second == sector) + { + if(i == sectors.begin()) + return NULL; + i--; + return i->second; + } + } + std::cerr << "Warning: Sector not found on level\n"; + return NULL; +} + +int +Level::get_total_sectors() +{ +return sectors.size(); +} + int Level::get_total_badguys() { diff --git a/src/level.h b/src/level.h index 9a5d3db6a..3e34d072d 100644 --- a/src/level.h +++ b/src/level.h @@ -61,6 +61,13 @@ public: Sector* get_sector(const std::string& name); + Sector* get_next_sector(const Sector* sector); + Sector* get_previous_sector(const Sector* sector); + + const std::string& get_sector_name(const Sector* sector); + + int get_total_sectors(); + int get_total_badguys(); int get_total_coins(); diff --git a/src/level_subset.cpp b/src/level_subset.cpp index 704ced19f..5cd4d2abd 100644 --- a/src/level_subset.cpp +++ b/src/level_subset.cpp @@ -76,7 +76,7 @@ void LevelSubset::read_info_file(const std::string& info_file) lisp_free(root_obj); } -void LevelSubset::load(const char* subset) +void LevelSubset::load(const std::string& subset) { name = subset; @@ -170,6 +170,7 @@ LevelSubset::get_level_filename(unsigned int num) { assert(num < levels.size()); +std::cerr << "levels[" << num << "]: " << levels[num] << std::endl; return directory + levels[num]; } diff --git a/src/level_subset.h b/src/level_subset.h index b4f64f697..4b9985ecc 100644 --- a/src/level_subset.h +++ b/src/level_subset.h @@ -48,7 +48,7 @@ public: ~LevelSubset(); static void create(const std::string& subset_name); - void load(const char* subset); + void load(const std::string& filename); void save(); void add_level(const std::string& name); diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp index 7be8284ba..2cf77d5ef 100644 --- a/src/leveleditor.cpp +++ b/src/leveleditor.cpp @@ -1,1808 +1,967 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2003 Ricardo Cruz -// Copyright (C) 2003 Tobias Glaesser -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include -#include -#include -#include -#include -#include +/*************************************************************************** + leveleditor.cpp - built'in leveleditor + ------------------- + begin : June, 23 2004 + copyright : (C) 2004 by Ricardo Cruz + email : rick2@aeiou.pt + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include #include -#include -#include -#include "SDL.h" -#include "SDL_image.h" - -#include "leveleditor.h" -#include "video/screen.h" -#include "defines.h" -#include "app/globals.h" +#include "gui/mousecursor.h" +#include "gui/menu.h" +#include "gui/button.h" +#include "audio/sound_manager.h" +#include "app/gettext.h" #include "app/setup.h" -#include "sector.h" -#include "tilemap.h" -#include "gameloop.h" -#include "badguy.h" -#include "player.h" -#include "scene.h" +#include "app/globals.h" +#include "special/sprite.h" +#include "leveleditor.h" +#include "resources.h" #include "tile.h" +#include "tilemap.h" #include "tile_manager.h" -#include "resources.h" +#include "sector.h" #include "background.h" -#include "camera.h" +#include "gameloop.h" +#include "badguy.h" +#include "gameobjs.h" +#include "door.h" -/* definitions to aid development */ +LevelEditor::LevelEditor() +{ +show_grid = true; + +selection.clear(); +global_frame_counter = 0; +frame_timer.init(true); +level_name_timer.init(true); +selection_end = selection_ini = Vector(0,0); +left_button = false; +middle_button = false; + +cur_layer = LAYER_TILES; +level_changed = false; + +sector = 0; +zoom = 1.0; + +/* Creating menus */ +level_subsets = FileSystem::dsubdirs("/levels", "info"); +subset_menu = new Menu(); +subset_menu->additem(MN_LABEL,_("Load Subset"),0,0); +subset_menu->additem(MN_HL,"",0,0); +int i = 0; +for(std::set::iterator it = level_subsets.begin(); it != level_subsets.end(); ++it, ++i) +{ +std::cerr << "adding entry level subset " << i << " entry: " << (*it) << std::endl; + subset_menu->additem(MN_ACTION, (*it),0,0,i); +} +subset_menu->additem(MN_HL,"",0,0); +subset_menu->additem(MN_BACK,_("Back"),0,0); + +create_subset_menu = new Menu(); +create_subset_menu->additem(MN_LABEL,_("New Level Subset"),0,0); +create_subset_menu->additem(MN_HL,"",0,0); +create_subset_menu->additem(MN_TEXTFIELD,_("Filename "),0,0,MN_ID_FILENAME_SUBSET); +create_subset_menu->additem(MN_TEXTFIELD,_("Title "),0,0,MN_ID_TITLE_SUBSET); +create_subset_menu->additem(MN_TEXTFIELD,_("Description"),0,0,MN_ID_DESCRIPTION_SUBSET); +create_subset_menu->additem(MN_ACTION,_("Create"),0,0, MN_ID_CREATE_SUBSET); +create_subset_menu->additem(MN_HL,"",0,0); +create_subset_menu->additem(MN_BACK,_("Back"),0,0); + +main_menu = new Menu(); +main_menu->additem(MN_LABEL,_("Level Editor Menu"),0,0); +main_menu->additem(MN_HL,"",0,0); +main_menu->additem(MN_ACTION,_("Return to Level Editor"),0,0,MN_ID_RETURN); +main_menu->additem(MN_GOTO,_("Create Level Subset"),0,create_subset_menu); +main_menu->additem(MN_GOTO,_("Load Level Subset"),0,subset_menu); +main_menu->additem(MN_HL,"",0,0); +main_menu->additem(MN_ACTION,_("Quit Level Editor"),0,0,MN_ID_QUIT); + +settings_menu = new Menu(); +settings_menu->additem(MN_LABEL,_("Level Settings"),0,0); +settings_menu->additem(MN_HL,"",0,0); +settings_menu->additem(MN_TEXTFIELD,_("Name "),0,0,MN_ID_NAME); +settings_menu->additem(MN_TEXTFIELD,_("Author "),0,0,MN_ID_AUTHOR); +settings_menu->additem(MN_NUMFIELD, _("Width "),0,0,MN_ID_WIDTH); +settings_menu->additem(MN_NUMFIELD, _("Height "),0,0,MN_ID_HEIGHT); +settings_menu->additem(MN_HL,"",0,0); +settings_menu->additem(MN_ACTION,_("Apply"),0,0,MN_ID_APPLY_SETTINGS); + +/* Creating button groups */ +load_buttons_gfx(); + +tiles_board = new ButtonGroup(Vector(screen->w - 140, 100), + Vector(32,32), Vector(4,8)); + +TileManager* tilemanager = TileManager::instance(); + +tiles_board->add_button(Button(img_rubber_bt, _("Eraser"), SDLKey(SDLK_DELETE)), 0); +for(unsigned int id = 1; id < tilemanager->total_ids(); id++) + { + Tile* tile = tilemanager->get(id); + if(!tile) + continue; + + Surface* surface; + if(tile->editor_images.size()) + surface = tile->editor_images[0]; + else if(tile->images.size()) + surface = tile->images[0]; + else + continue; -/* definitions that affect gameplay */ -#define KEY_CURSOR_SPEED 32 -#define KEY_CURSOR_FASTSPEED 64 + Button button = Button(surface, "", SDLKey(0)); + tiles_board->add_button(button, id); + } +for(int i = 0; i < NUM_BadGuyKinds; i++) + { + BadGuyKind kind = BadGuyKind(i); + BadGuy badguy(kind, 0,0); + badguy.activate(LEFT); -/* when pagedown/up pressed speed:*/ -#define PAGE_CURSOR_SPEED 13*32 + Surface *img = badguy.get_image(); + tiles_board->add_button(Button(img, "", SDLKey(SDLK_1+i)), -(i+1)); + } -#define MOUSE_LEFT_MARGIN 80 -#define MOUSE_RIGHT_MARGIN (560-32) +tiles_board->add_button(Button(img_trampoline[0].get_frame(0), _("Trampoline"), SDLKey(0)), OBJ_TRAMPOLINE); +tiles_board->add_button(Button(img_flying_platform->get_frame(0), _("Flying Platform"), SDLKey(0)), OBJ_FLYING_PLATFORM); +tiles_board->add_button(Button(door->get_frame(0), _("Door"), SDLKey(0)), OBJ_DOOR); + +tiles_layer = new ButtonGroup(Vector(12, screen->h-64), Vector(80,20), Vector(1,3)); +tiles_layer->add_button(Button(img_foreground_bt, _("Edtit foreground tiles"), + SDLK_F10), LAYER_FOREGROUNDTILES); +tiles_layer->add_button(Button(img_interactive_bt, _("Edit interactive tiles"), + SDLK_F11), LAYER_TILES, true); +tiles_layer->add_button(Button(img_background_bt, _("Edit background tiles"), + SDLK_F12), LAYER_BACKGROUNDTILES); + +level_options = new ButtonGroup(Vector(screen->w-164, screen->h-36), Vector(32,32), Vector(5,1)); +level_options->add_pair_of_buttons(Button(img_next_sector_bt, _("Next sector"), SDLKey(0)), BT_NEXT_SECTOR, + Button(img_previous_sector_bt, _("Prevous sector"), SDLKey(0)), BT_PREVIOUS_SECTOR); +level_options->add_pair_of_buttons(Button(img_next_level_bt, _("Next level"), SDLKey(0)), BT_NEXT_LEVEL, + Button(img_previous_level_bt, _("Prevous level"), SDLKey(0)), BT_PREVIOUS_LEVEL); +level_options->add_button(Button(img_save_level_bt, _("Save level"), SDLK_F5), BT_LEVEL_SAVE); +level_options->add_button(Button(img_test_level_bt, _("Test level"), SDLK_F6), BT_LEVEL_TEST); +level_options->add_button(Button(img_setup_level_bt, _("Setup level"), SDLK_F7), BT_LEVEL_SETUP); +} -/* scolling speed */ -#define KEYBOARD_SPEED 140 -#define MOUSE_SPEED 40 +LevelEditor::~LevelEditor() +{ +free_buttons_gfx(); -/* look */ -#define SELECT_W 2 // size of the selections lines -#define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A) +delete tiles_board; +delete tiles_layer; +delete level_options; -/* Frames per second: */ +delete subset_menu; +delete create_subset_menu; +delete main_menu; +delete settings_menu; +} -#define FPS (1000 / 25) +void LevelEditor::load_buttons_gfx() +{ +img_foreground_bt = new Surface(datadir + "/images/leveleditor/foreground.png", true); +img_interactive_bt = new Surface(datadir + "/images/leveleditor/interactive.png", true); +img_background_bt = new Surface(datadir + "/images/leveleditor/background.png", true); -enum { TM_IA, TM_BG, TM_FG }; +img_save_level_bt = new Surface(datadir + "/images/leveleditor/save-level.png", true); +img_test_level_bt = new Surface(datadir + "/images/leveleditor/test-level.png", true); +img_setup_level_bt = new Surface(datadir + "/images/leveleditor/setup-level.png", true); -LevelEditor::LevelEditor() -{ - level_subsets = FileSystem::dsubdirs("/levels", "level1.stl"); - le_level_subset = new LevelSubset; - - le_level = NULL; - le_levelnb = 1; - selected_game_object = NULL; - - active_tm = TM_IA; - le_show_grid = true; - show_selections = true; - - pos_x = pos_y = 0; - - done = 0; - le_frame = 0; /* support for frames in some tiles, like waves and bad guys */ - le_level_changed = false; - le_help_shown = false; - - le_mouse_pressed[LEFT] = false; - le_mouse_pressed[RIGHT] = false; - - le_mouse_clicked[LEFT] = false; - le_mouse_clicked[RIGHT] = false; - - le_selection = new Surface(datadir + "/images/leveleditor/select.png", true); - - select_tilegroup_menu_effect.init(false); - select_objects_menu_effect.init(false); - display_level_info.init(false); - - /* Load buttons */ - le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32); - le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32); - le_next_level_bt = new Button("/images/icons/next.png","Next level", SDLK_PAGEUP,screen->w-64,0); - le_previous_level_bt = new Button("/images/icons/previous.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0); - le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48); - le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48); - le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48); - le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64); - le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64); - le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,screen->w-80-16,0); - le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0); - le_move_up_bt = new Button("/images/icons/up.png","Move up",SDLK_UP,screen->w-80,16); - le_move_down_bt = new Button("/images/icons/down.png","Move down",SDLK_DOWN,screen->w-80,32); - le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64); - le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80); - le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98); - le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98); - le_object_properties_bt->set_active(false); - - mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1); - mouse_select_object->set_mid(16,16); - - le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32); - le_tilemap_panel->set_button_size(32,10); - le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG); - le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0), TM_IA); - le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG); - le_tilemap_panel->highlight_last(true); - le_tilemap_panel->set_last_clicked(TM_IA); - - le_current.Init(); - - init_menus(); - - SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); -} +img_rubber_bt = new Surface(datadir + "/images/leveleditor/rubber.png", true); -LevelEditor::~LevelEditor() -{ - SDL_EnableKeyRepeat(0, 0); // disables key repeating - - unload_level(); - delete le_selection; - delete leveleditor_menu; - delete subset_load_menu; - delete subset_new_menu; - delete subset_settings_menu; - delete level_settings_menu; - delete select_tilegroup_menu; - delete select_objects_menu; - delete le_save_level_bt; - delete le_exit_bt; - delete le_test_level_bt; - delete le_next_level_bt; - delete le_previous_level_bt; - delete le_move_right_bt; - delete le_move_left_bt; - delete le_move_up_bt; - delete le_move_down_bt; - delete le_rubber_bt; - delete le_select_mode_one_bt; - delete le_select_mode_two_bt; - delete le_settings_bt; - delete le_tilegroup_bt; - delete le_objects_bt; - delete le_tilemap_panel; - delete le_object_select_bt; - delete le_object_properties_bt; - delete mouse_select_object; - - delete le_level_subset; - le_level_subset = 0; - - for(ButtonPanelMap::iterator i = tilegroups_map.begin(); - i != tilegroups_map.end(); ++i) - { - delete i->second; - } - for(ButtonPanelMap::iterator i = objects_map.begin(); - i != objects_map.end(); ++i) - { - delete i->second; - } +img_previous_level_bt = new Surface(datadir + "/images/leveleditor/previous-level.png", true); +img_next_level_bt = new Surface(datadir + "/images/leveleditor/next-level.png", true); +img_previous_sector_bt = new Surface(datadir + "/images/leveleditor/previous-sector.png", true); +img_next_sector_bt = new Surface(datadir + "/images/leveleditor/next-sector.png", true); } -int LevelEditor::run(char* filename) +void LevelEditor::free_buttons_gfx() { - int last_time, now_time, i; - DrawingContext context; +delete img_foreground_bt; +delete img_interactive_bt; +delete img_background_bt; - le_level = NULL; - le_levelnb = 1; +delete img_save_level_bt; +delete img_test_level_bt; +delete img_setup_level_bt; - SoundManager::get()->halt_music(); +delete img_rubber_bt; - while (SDL_PollEvent(&event)) - {} - - if(filename != NULL) - if(load_level_subset(filename)) - return 1; +delete img_previous_level_bt; +delete img_next_level_bt; +delete img_previous_sector_bt; +delete img_next_sector_bt; +} - while(true) - { - last_time = SDL_GetTicks(); - le_frame++; +void LevelEditor::run(const std::string filename) +{ +SoundManager::get()->halt_music(); +Menu::set_current(0); - checkevents(); +DrawingContext context; - if(Menu::current() == select_tilegroup_menu) - { - if(select_tilegroup_menu_effect.check()) - { - select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(), - 66,-0.5,0.5); - } - else - select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5); - } - else if(Menu::current() == select_objects_menu) - { - if(select_objects_menu_effect.check()) - { - select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5); - } - else - select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5); - } +if(!filename.empty()) + load_level(filename); +else + Menu::set_current(main_menu); - if(le_level != NULL) - { - /* making events results to be in order */ +mouse_cursor->set_state(MC_NORMAL); - /* draw the level */ - context.set_translation(Vector(pos_x, pos_y)); - drawlevel(context); - } - else - fillrect(0, 0, screen->w, screen->h, 0, 0, 0); +done = false; +while(!done) + { + events(); + action(); + draw(context); + } - /* draw editor interface */ - context.set_translation(Vector(0, 0)); - drawinterface(context); +if(level_changed) + if(confirm_dialog(NULL, _("Level not saved. Wanna to?"))) + save_level(); +} - Menu* menu = Menu::current(); - if(menu) +void LevelEditor::events() +{ +while(SDL_PollEvent(&event)) + { + Menu* menu = Menu::current(); + if(menu) { - menu->draw(context); - menu->action(); - - if(menu == leveleditor_menu) + menu->event(event); + menu->action(); + if(menu == main_menu) { - switch (leveleditor_menu->check()) + switch (main_menu->check()) { - case MNID_RETURNLEVELEDITOR: - if(le_level != NULL) - Menu::set_current(0); - else - Menu::set_current(leveleditor_menu); - break; - case MNID_SUBSETSETTINGS: - update_subset_settings_menu(); + case MN_ID_RETURN: + Menu::set_current(0); break; - case MNID_QUITLEVELEDITOR: - done = 1; + case MN_ID_QUIT: + done = true; break; } } - else if(menu == level_settings_menu) + else if(menu == create_subset_menu) { - switch (level_settings_menu->check()) - { - case MNID_APPLY: - apply_level_settings_menu(); - Menu::set_current(NULL); - break; + if(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input[0] == '\0') + create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_DEACTIVE; + else if(create_subset_menu->check() == MN_ID_CREATE_SUBSET) + { // applying settings: + LevelSubset::create(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input); + level_subset.load(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input); - default: - break; + level_subset.title = create_subset_menu->item[MN_ID_TITLE_SUBSET].input; + level_subset.description = create_subset_menu->item[MN_ID_DESCRIPTION_SUBSET].input; + + load_level(1); + + create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).change_input(""); + create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).change_input(""); + create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).change_input(""); } } - else if(menu == select_tilegroup_menu) + else if(menu == subset_menu) { - int it = -1; - switch (it = select_tilegroup_menu->check()) + int i = subset_menu->check(); + if(i >= 0) { - default: - if(it >= 0) - { - cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text; - Menu::set_current(0); - cur_objects = ""; - - } - break; + std::set::iterator it = level_subsets.begin(); + for(int t = 0; t < i; t++) + it++; +std::cerr << "load subset level_subsets " << i << ": " << (*it) << std::endl; + load_level_subset(*it); + Menu::set_current(0); } } - else if(menu == select_objects_menu) + else if(menu == settings_menu) { - int it = -1; - switch (it = select_objects_menu->check()) - { - default: - if(it >= 0) - { - cur_objects = select_objects_menu->get_item_by_id(it).text; - cur_tilegroup = ""; + if(settings_menu->check() == MN_ID_APPLY_SETTINGS) + { // applying settings: + level_changed = true; - Menu::set_current(0); - } - break; + level.name = settings_menu->get_item_by_id(MN_ID_NAME).input; + level.author = settings_menu->get_item_by_id(MN_ID_AUTHOR).input; + + solids->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), + atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); + foregrounds->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), + atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); + backgrounds->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), + atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); + + Menu::set_current(0); } } - else if(menu == subset_load_menu) + } + // check for events in buttons + else if(tiles_board->event(event)) + { + std::vector vector; + vector.push_back(tiles_board->selected_id()); + + selection.clear(); + selection.push_back(vector); + continue; + } + else if(tiles_layer->event(event)) + { + cur_layer = tiles_layer->selected_id(); + continue; + } + else if(level_options->event(event)) + { + switch(level_options->selected_id()) { - switch (i = subset_load_menu->check()) - { - case 0: - break; - default: - if(i >= 1) + case BT_LEVEL_SAVE: + save_level(); + break; + case BT_LEVEL_TEST: + test_level(); + break; + case BT_LEVEL_SETUP: + Menu::set_current(settings_menu); + break; + case BT_NEXT_LEVEL: + if(level_nb < level_subset.get_num_levels()) + load_level(level_nb + 1); + else { - if(load_level_subset(subset_load_menu->item[i+1].text.c_str())) - return 1; + Level new_lev; + char str[1024]; + sprintf(str,_("Level %d doesn't exist. Create it?"), level_nb + 1); + if(confirm_dialog(NULL, str)) + { + level_subset.add_level("new_level.stl"); + new_lev.save(level_subset.get_level_filename(level_nb + 1)); + load_level(level_nb); + } } - break; - } + break; + case BT_PREVIOUS_LEVEL: + if(level_nb > 1) + load_level(level_nb - 1); + break; + case BT_NEXT_SECTOR: +std::cerr << "next sector.\n"; +std::cerr << "total sectors: " << level.get_total_sectors() << std::endl; + load_sector(level.get_next_sector(sector)); + break; + case BT_PREVIOUS_SECTOR: +std::cerr << "previous sector.\n"; + load_sector(level.get_previous_sector(sector)); + break; } - else if(menu == subset_new_menu) + level_options->set_unselected(); + continue; + } + else + { + switch(event.type) { - if(subset_new_menu->item[2].input[0] == '\0') - subset_new_menu->item[3].kind = MN_DEACTIVE; - else - { - subset_new_menu->item[3].kind = MN_ACTION; + case SDL_MOUSEMOTION: + if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT)) + { // movement like in strategy games + scroll.x += -1 * event.motion.xrel; + scroll.y += -1 * event.motion.yrel; + } + break; + + case SDL_MOUSEBUTTONDOWN: + if(event.button.button == SDL_BUTTON_LEFT) + left_button = true; + else if(event.button.button == SDL_BUTTON_MIDDLE) + { + middle_button = true; + selection_ini = Vector(event.button.x, event.button.y); + } + break; + + case SDL_MOUSEBUTTONUP: + if(event.button.button == SDL_BUTTON_LEFT) + left_button = false; + else if(event.button.button == SDL_BUTTON_MIDDLE) + { + middle_button = false; + selection_end = Vector(event.button.x, event.button.y); + + if(selection_end.x < selection_ini.x) + { + float t = selection_ini.x; + selection_ini.x = selection_end.x; + selection_end.x = t; + } + if(selection_end.y < selection_ini.y) + { + float t = selection_ini.y; + selection_ini.y = selection_end.y; + selection_end.y = t; + } + + selection.clear(); + std::vector vector; - switch (i = subset_new_menu->check()) + TileMap* tilemap = 0; + if(cur_layer == LAYER_FOREGROUNDTILES) + tilemap = foregrounds; + else if(cur_layer == LAYER_TILES) + tilemap = solids; + else if(cur_layer == LAYER_BACKGROUNDTILES) + tilemap = backgrounds; + + for(int x = 0; x < (int)((selection_end.x - selection_ini.x)*zoom / 32) + 1; x++) + { + vector.clear(); + for(int y = 0; y < (int)((selection_end.y - selection_ini.y)*zoom / 32) + 1; y++) + { + vector.push_back(tilemap->get_tile(x + + (int)(((selection_ini.x+scroll.x)*zoom)/32), + y + (int)(((selection_ini.y+scroll.y)*zoom)/32))->id); + } + selection.push_back(vector); + } + } + break; + + case SDL_KEYDOWN: // key pressed + switch(event.key.keysym.sym) { - case MNID_CREATESUBSET: - LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input); - le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input.c_str()); - leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO; - goto_level(1); - subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input(""); - - Menu::set_current(subset_settings_menu); + case SDLK_ESCAPE: + Menu::set_current(main_menu); + break; + /* scrolling related events: */ + case SDLK_HOME: + scroll.x = 0; + break; + case SDLK_END: + scroll.x = sector->solids->get_height()*32 - screen->w; + break; + case SDLK_LEFT: + scroll.x -= 80; + break; + case SDLK_RIGHT: + scroll.x += 80; + break; + case SDLK_UP: + scroll.y -= 80; + break; + case SDLK_DOWN: + scroll.y += 80; + break; + case SDLK_PAGEUP: + scroll.x -= 450; + break; + case SDLK_PAGEDOWN: + scroll.x += 450; + break; + case SDLK_PLUS: + case SDLK_KP_PLUS: + zoom += 0.10; + break; + case SDLK_MINUS: + case SDLK_KP_MINUS: + zoom -= 0.10; + break; + + case SDLK_F1: + show_help(); + break; + case SDLK_F2: + show_grid = !show_grid; + break; + default: break; } - } - } - else if(menu == subset_settings_menu) - { - if(le_level_subset->title.compare(subset_settings_menu->get_item_by_id(MNID_SUBSETTITLE).input) == 0 && le_level_subset->description.compare(subset_settings_menu->get_item_by_id(MNID_SUBSETDESCRIPTION).input) == 0 ) - subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE; - else - subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION; + break; - switch (i = subset_settings_menu->check()) - { - case MNID_SUBSETSAVECHANGES: - save_subset_settings_menu(); - Menu::set_current(leveleditor_menu); + case SDL_QUIT: // window closed + done = true; + break; + + default: break; - } } } + } +} - MouseCursor::current()->draw(context); +void LevelEditor::action() +{ +mouse_cursor->set_state(MC_NORMAL); +if(tiles_board->is_hover() || tiles_layer->is_hover() || level_options->is_hover()) + mouse_cursor->set_state(MC_LINK); - if(done) +if(sector) + { + if(!frame_timer.check()) { - return 0; - } - + frame_timer.start(25); ++global_frame_counter; + } - SDL_Delay(25); - now_time = SDL_GetTicks(); - if (now_time < last_time + FPS) - SDL_Delay(last_time + FPS - now_time); /* delay some time */ - - context.do_drawing(); + // don't scroll before the start or after the level's end + float width = sector->solids->get_width() * 32; + float height = sector->solids->get_height() * 32; + + if(scroll.x < -screen->w/2) + scroll.x = -screen->w/2; + if(scroll.x > width - screen->w/2) + scroll.x = width - screen->w/2; + if(scroll.y < -screen->h/2) + scroll.y = -screen->h/2; + if(scroll.y > height - screen->h/2) + scroll.y = height - screen->h/2; + + if(left_button) + for(unsigned int x = 0; x < selection.size(); x++) + for(unsigned int y = 0; y < selection[x].size(); y++) + change((int)((scroll.x + event.button.x)/(32*zoom)) + x, + (int)((scroll.y + event.button.y)/(32*zoom)) + y, selection[x][y], + cur_layer); } - - return done; } -int LevelEditor::load_level_subset(const char *filename) +void LevelEditor::draw(DrawingContext& context) { - le_level_subset->load(filename); - leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO; - le_levelnb = 1; - goto_level(le_levelnb); - - //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME); +context.draw_text(white_text, _("Level Editor"), Vector(10, 5), LEFT_ALLIGN, LAYER_GUI); +mouse_cursor->draw(context); - Menu::set_current(NULL); +// draw a filled background +context.draw_filled_rect(Vector(0,0), Vector(screen->w,screen->h), Color(60,60,60), LAYER_BACKGROUND0-1); - return 0; -} - -void LevelEditor::init_menus() -{ - int i = 0; - - leveleditor_menu = new Menu(); - subset_load_menu = new Menu(); - subset_new_menu = new Menu(); - subset_settings_menu = new Menu(); - level_settings_menu = new Menu(); - select_tilegroup_menu = new Menu(); - select_objects_menu = new Menu(); - - leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0); - leveleditor_menu->additem(MN_HL,"",0,0); - leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR); - leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS); - leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu); - leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu); - leveleditor_menu->additem(MN_HL,"",0,0); - leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR); - - Menu::set_current(leveleditor_menu); - - subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0); - subset_load_menu->additem(MN_HL, "", 0, 0); - - for(std::set::iterator it = level_subsets.begin(); it != level_subsets.end(); ++it) +if(level_name_timer.check()) + { + context.draw_text(gold_text, level.name, Vector(screen->w/2, 30), CENTER_ALLIGN, LAYER_GUI); + char str[128]; + sprintf(str, "%i/%i", level_nb+1, level_subset.get_num_levels()); + context.draw_text(gold_text, str, Vector(screen->w/2, 50), CENTER_ALLIGN, LAYER_GUI); + } +if(sector) + context.draw_text(white_small_text, _("F1 for help"), Vector(5, 510), LEFT_ALLIGN, LAYER_GUI-10); +else + context.draw_text(white_small_text, _("Choose a level subset"), Vector(5, 510), LEFT_ALLIGN, LAYER_GUI-10); + +Menu* menu = Menu::current(); +if(menu) + menu->draw(context); +else { - subset_load_menu->additem(MN_ACTION,(*it),0,0, i+1); + tiles_board->draw(context); + tiles_layer->draw(context); + level_options->draw(context); } - subset_load_menu->additem(MN_HL,"",0,0); - subset_load_menu->additem(MN_BACK,"Back",0,0); - - subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0); - subset_new_menu->additem(MN_HL,"",0,0); - subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME); - subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET); - subset_new_menu->additem(MN_HL,"",0,0); - subset_new_menu->additem(MN_BACK,"Back",0,0); - - subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0); - subset_settings_menu->additem(MN_HL,"",0,0); - subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE); - subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION); - subset_settings_menu->additem(MN_HL,"",0,0); - subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES); - subset_settings_menu->additem(MN_HL,"",0,0); - subset_settings_menu->additem(MN_BACK,"Back",0,0); - - level_settings_menu->arrange_left = true; - level_settings_menu->additem(MN_LABEL,"Level Settings",0,0); - level_settings_menu->additem(MN_HL,"",0,0); - level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME); - level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR); - level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG); - level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG); - level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE); - level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH); - level_settings_menu->additem(MN_NUMFIELD, "Height ",0,0,MNID_HEIGHT); - level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME); - level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY); - level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED); - level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed); - level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen); - level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue); - level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed); - level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen); - level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue); - level_settings_menu->additem(MN_HL,"",0,0); - level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY); - - select_tilegroup_menu->arrange_left = true; - select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0); - select_tilegroup_menu->additem(MN_HL,"",0,0); - std::set* tilegroups = TileManager::tilegroups(); - int tileid = 1; - for(std::set::iterator it = tilegroups->begin(); - it != tilegroups->end(); ++it ) + +// draw selection +if(sector) + { + if(!middle_button) { - select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid); - tileid++; - tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318); - i = 0; + context.set_drawing_effect(SEMI_TRANSPARENT); - for(std::vector::const_iterator sit = (*it).tiles.begin(); - sit != (*it).tiles.end(); ++sit, ++i) + if(selection.size()) { -/* Tile& tile = TileManager::instance()->get(*sit); - Surface* image; - if(tile.editor_images.size() > 0) - image = tile.editor_images[0]; - else if(tile.images.size() > 0) - image = tile.images[0]; + if(selection[0][0] == 0 && selection.size() == 1) + context.draw_surface(img_rubber_bt, Vector(event.button.x - 8, + event.button.y - 8), LAYER_GUI-2); + else if(selection[0][0] < 0) + { + int id = selection[0][0]; + + if(id == OBJ_TRAMPOLINE) + context.draw_surface(img_trampoline[0].get_frame(0), Vector(event.button.x - 8, + event.button.y - 8), LAYER_GUI-2); + else if(id == OBJ_FLYING_PLATFORM) + context.draw_surface(img_flying_platform->get_frame(0), Vector(event.button.x - 8, + event.button.y - 8), LAYER_GUI-2); + else if(id == OBJ_DOOR) + context.draw_surface(door->get_frame(0), Vector(event.button.x - 8, + event.button.y - 8), LAYER_GUI-2); else - // TODO use some notile image... - image = 0; + { + BadGuyKind kind = BadGuyKind((-id)-1); + BadGuy badguy(kind, 0,0); + badguy.activate(LEFT); + Surface *img = badguy.get_image(); - Button* button = new Button(image, it->name, SDLKey(SDLK_a + i), - 0, 0, 32, 32); - tilegroups_map[it->name]->additem(button, *sit);*/ + context.draw_surface(img, Vector(event.button.x - 8, + event.button.y - 8), LAYER_GUI-2); + } + } + else + { + TileManager* tilemanager = TileManager::instance(); + for(unsigned int x = 0; x < selection.size(); x++) + for(unsigned int y = 0; y < selection[x].size(); y++) + tilemanager->draw_tile(context, selection[x][y], + Vector(event.button.x + x*32 - 8, event.button.y + y*32 - 8), + LAYER_GUI-2); + } } + context.set_drawing_effect(NONE_EFFECT); } - select_tilegroup_menu->additem(MN_HL,"",0,0); - - select_objects_menu->arrange_left = true; - select_objects_menu->additem(MN_LABEL,"Objects",0,0); - select_objects_menu->additem(MN_HL,"",0,0); - // TODO fix this - select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1); - objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318); - - for(int i = 0; i < NUM_BadGuyKinds; ++i) - { -// BadGuy bad_tmp(BadGuyKind(i), 0, 0); -// objects_map["BadGuys"]->additem(new Button(0, "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i); -/* FIXME: maybe addbutton should already have a parameter for the surface - objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new - BadGuy(BadGuyKind(i), - objects_map["BadGuys"]->manipulate_button(i)->get_pos().x, - objects_map["BadGuys"]->manipulate_button(i)->get_pos().y - ));*/ - } - - select_objects_menu->additem(MN_HL,"",0,0); + else + context.draw_filled_rect(Vector(std::min((int)selection_ini.x, (int)event.button.x)*zoom, + std::min((int)selection_ini.y, (int)event.button.y))*zoom, + Vector(abs(event.button.x - (int)selection_ini.x)*zoom, + abs(event.button.y - (int)selection_ini.y)*zoom), + Color(170,255,170,128), LAYER_GUI-2); -} + if(show_grid) + { + for(int x = 0; x < screen->w / (32*zoom); x++) + { + int pos = (int)(x*32*zoom) - ((int)scroll.x % 32); + context.draw_filled_rect(Vector (pos, 0), Vector(1, screen->h), + Color(225, 225, 225), LAYER_GUI-50); + } + for(int y = 0; y < screen->h / (32*zoom); y++) + { + int pos = (int)(y*32*zoom) - ((int)scroll.y % 32); + context.draw_filled_rect(Vector (0, pos), Vector(screen->w, 1), + Color(225, 225, 225), LAYER_GUI-50); + } + } -void LevelEditor::update_level_settings_menu() -{ - char str[80]; - std::set::iterator it; - - level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_level->name.c_str()); - level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_level->author.c_str()); - - level_settings_menu->get_item_by_id(MNID_SONG).list.first = FileSystem::dfiles("music/","", "-fast"); - level_settings_menu->get_item_by_id(MNID_BGIMG).list.first = FileSystem::dfiles("images/background","", ""); - level_settings_menu->get_item_by_id(MNID_BGIMG).list.first.insert(""); - level_settings_menu->get_item_by_id(MNID_PARTICLE).list.first.insert(""); - level_settings_menu->get_item_by_id(MNID_PARTICLE).list.first.insert("snow"); - level_settings_menu->get_item_by_id(MNID_PARTICLE).list.first.insert("clouds"); - - if((it = level_settings_menu->get_item_by_id(MNID_SONG).list.first.find(le_level->get_sector("main")->song_title)) != level_settings_menu->get_item_by_id(MNID_SONG).list.first.end()) - level_settings_menu->get_item_by_id(MNID_SONG).list.second = it; - if((it = level_settings_menu->get_item_by_id(MNID_BGIMG).list.first.find(le_level->get_sector("main")->background->get_image())) != level_settings_menu->get_item_by_id(MNID_BGIMG).list.first.end()) - level_settings_menu->get_item_by_id(MNID_BGIMG).list.second = it; -/* if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_level->get_sector("main")->particlesystem.c_str())) != -1) - level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;*/ - - sprintf(str,"%d",static_cast(le_level->get_sector("main")->solids->get_width())); - level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str); - sprintf(str,"%d", static_cast(le_level->get_sector("main")->solids->get_height())); - level_settings_menu->get_item_by_id(MNID_HEIGHT).change_input(str); - sprintf(str,"%d",le_level->time_left); - level_settings_menu->get_item_by_id(MNID_TIME).change_input(str); - sprintf(str,"%2.0f",le_level->get_sector("main")->gravity); - level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str); - sprintf(str,"%2.2f", le_level->get_sector("main")->background->get_speed()); - level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str); - sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().red); - level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str); - sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().green); - level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str); - sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_top().blue); - level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str); - sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().red); - level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str); - sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().green); - level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str); - sprintf(str,"%d",le_level->get_sector("main")->background->get_gradient_bottom().blue); - level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str); -} + context.push_transform(); + context.set_translation(scroll); + context.set_zooming(zoom); -void LevelEditor::update_subset_settings_menu() -{ - subset_settings_menu->item[2].change_input(le_level_subset->title.c_str()); - subset_settings_menu->item[3].change_input(le_level_subset->description.c_str()); -} + for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); ++i) + { + TileMap* tilemap = dynamic_cast (*i); + if(tilemap) + { // draw the non-selected tiles semi-transparently + context.push_transform(); -void LevelEditor::apply_level_settings_menu() -{ - int i; - i = false; - le_level_changed = true; + if(tilemap->get_layer() != cur_layer) + context.set_drawing_effect(SEMI_TRANSPARENT); + (*i)->draw(context); - le_level->name = level_settings_menu->get_item_by_id(MNID_NAME).input; - le_level->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input; + context.pop_transform(); + } + Background* background = dynamic_cast (*i); + if(background) + { // don't resize background + context.push_transform(); + context.set_translation(scroll); + context.set_zooming(1.0); + (*i)->draw(context); + context.pop_transform(); + } + else + (*i)->draw(context); + } - if(le_level->get_sector("main")->background->get_image().compare((*level_settings_menu->get_item_by_id(MNID_BGIMG).list.second)) != 0) - { - le_level->get_sector("main")->background->set_image((*level_settings_menu->get_item_by_id(MNID_BGIMG).list.second), atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input.c_str())); - i = true; + context.pop_transform(); } +else + context.draw_filled_rect(Vector(0,0), Vector(screen->w,screen->h),Color(0,0,0), LAYER_BACKGROUND0); -/* if(le_level->get_sector("main")->particlesystem.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0) - { - le_level->->get_sector("main")->particlesystem = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list); - }*/ - -/* if(i) - { - le_level->load_gfx(); - }*/ - - le_level->get_sector("main")->song_title = (*level_settings_menu->get_item_by_id(MNID_SONG).list.second); - - le_level->get_sector("main")->solids->resize( - atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input.c_str()), - atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input.c_str())); - le_level->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input.c_str()); - le_level->get_sector("main")->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input.c_str()); - le_level->get_sector("main")->background->set_gradient(Color( - atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input.c_str()), - atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input.c_str()), - atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input.c_str())), Color( - atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input.c_str()), - atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input.c_str()), - atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input.c_str()))); +context.do_drawing(); } -void LevelEditor::save_subset_settings_menu() +void LevelEditor::load_level_subset(std::string filename) { - le_level_subset->title = subset_settings_menu->item[2].input; - le_level_subset->description = subset_settings_menu->item[3].input; - le_level_subset->save(); - le_level_changed = false; +std::cerr << "loading subset...\n"; +std::cerr << "filename: " << filename << std::endl; +level_subset.load(filename.c_str()); +load_level(1); } -void LevelEditor::unload_level() +void LevelEditor::load_level(std::string filename) { - if(le_level_changed) - { - char str[1024]; - // TODO get level number - sprintf(str,"Save changes to level %d of %s?", 0/*le_level*/,le_level_subset->name.c_str()); - Surface* surf = new Surface(le_level->get_sector("main")->background->get_image(), false); - if(confirm_dialog(surf, str)) - { - le_level->save(le_level_subset->get_level_filename(le_levelnb)); - } - if(surf != NULL) - delete surf; - } +if(!level_changed) + save_level(); - delete le_level; - le_level_changed = false; -} +level_filename = filename; +level.load(filename); -void LevelEditor::goto_level(int levelnb) -{ - unload_level(); - le_level = new Level(); - le_level->load(le_level_subset->get_level_filename(levelnb)); - display_level_info.start(2500); - le_levelnb = levelnb; +load_sector("main"); +level_name_timer.start(3000); +scroll.x = scroll.y = 0; +level_changed = false; + +settings_menu->get_item_by_id(MN_ID_NAME).change_input(level.name.c_str()); +settings_menu->get_item_by_id(MN_ID_AUTHOR).change_input(level.author.c_str()); } -void LevelEditor::drawminimap() +void LevelEditor::load_level(int nb) { -#if 0 -// if(le_level == NULL) -// return; - - int mini_tile_width; - if((unsigned)screen->w - 64 > le_level->get_sector("main")->solids->get_width() * 4) - mini_tile_width = 4; - else if((unsigned)screen->w - 64 > le_level->get_sector("main")->solids->get_width() * 2) - mini_tile_width = 2; - else - mini_tile_width = 1; - int left_offset = (screen->w - 64 - le_level->get_sector("main")->solids->get_width()*mini_tile_width) / 2; - - int mini_tile_height; - if((unsigned)screen->h > le_level->get_sector("main")->solids->get_height() * 4) - mini_tile_height = 4; - else if((unsigned)screen->h > le_level->get_sector("main")->solids->get_height() * 2) - mini_tile_height = 2; - else - mini_tile_height = 1; - - for (unsigned int y = 0; y < le_level->get_sector("main")->solids->get_height(); ++y) - for (unsigned int x = 0; x < le_level->get_sector("main")->solids->get_width(); ++x) - { +if(!level_changed) + save_level(); - Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height, - mini_tile_width , mini_tile_height, le_level->bg_tiles[y * le_level->get_sector("main")->solids->get_width() + x]); +level_nb = nb; +std::cerr << "level_nb: " << level_nb << std::endl; +std::cerr << "level_subset.get_level_filename(level_nb): " << level_subset.get_level_filename(level_nb) << std::endl; +level_filename = level_subset.get_level_filename(level_nb); - Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height, - mini_tile_width , mini_tile_height, le_level->ia_tiles[y * le_level->get_sector("main")->solids->get_width() + x]); - - Tile::draw_stretched(left_offset + mini_tile_width*x, y * mini_tile_height, - mini_tile_width , mini_tile_height, le_level->fg_tiles[y + le_level->get_sector("main")->solids->get_width() + x]); +load_level(level_filename); +} - } +void LevelEditor::load_sector(std::string name) +{ +sector_name = name; +sector = level.get_sector(sector_name); +if(!sector) + Termination::abort("Level has no " + sector_name + " sector.", ""); - fillrect(left_offset, 0, - le_level->get_sector("main")->solids->get_width()*mini_tile_width, le_level->get_sector("main")->solids->get_height()*mini_tile_height, - 200, 200, 200, 96); - - fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height, - (VISIBLE_TILES_X-3)*mini_tile_width, 2, - 200, 200, 200, 200); - fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height, - 2, (VISIBLE_TILES_Y-1)*mini_tile_height, - 200, 200, 200, 200); - fillrect(left_offset + (pos_x/32)*mini_tile_width + (VISIBLE_TILES_X-3)*mini_tile_width - 2, (pos_y/32)*mini_tile_height, - 2, (VISIBLE_TILES_Y-1)*mini_tile_height, - 200, 200, 200, 200); - fillrect(left_offset + (pos_x/32)*mini_tile_width, (pos_y/32)*mini_tile_height + (VISIBLE_TILES_Y-1)*mini_tile_height - 2, - (VISIBLE_TILES_X-3)*mini_tile_width, 2, - 200, 200, 200, 200); -#endif +load_sector(sector); } -void LevelEditor::drawinterface(DrawingContext &context) +void LevelEditor::load_sector(Sector* sector_) { - int x,y; - char str[80]; - - if(le_level != NULL) +if(sector == NULL) { - /* draw a grid (if selected) */ - if(le_show_grid) + if(confirm_dialog(NULL, _("No more sectors exist. Create another?"))) { - for(x = 0; x < VISIBLE_TILES_X; x++) - fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255); - for(y = 0; y < VISIBLE_TILES_Y; y++) - fillrect(0, y*32 - ((int)pos_y % 32), screen->w, 1, 225, 225, 225,255); + Sector* nsector = new Sector(); + level.add_sector(nsector); + sector = nsector; } + return; } - if(show_minimap) // use_gl because the minimap isn't shown correctly in software mode. Any idea? FIXME Possible reasons: SDL_SoftStretch is a hack itsself || an alpha blitting issue SDL can't handle in software mode - drawminimap(); - - if(show_selections && MouseCursor::current() != mouse_select_object) - { - if(le_selection_mode == CURSOR) - { - if(le_current.IsTile()) - context.draw_surface(le_selection, Vector(cursor_x - pos_x, cursor_y - pos_y), LAYER_GUI); - } - else if(le_selection_mode == SQUARE) - { - int w, h; - highlight_selection(); - /* draw current selection */ - w = selection.x2 - selection.x1; - h = selection.y2 - selection.y1; - context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y), Vector(w, SELECT_W), Color(SELECT_CLR), LAYER_GUI); - context.draw_filled_rect(Vector(selection.x1 - pos_x + w, selection.y1 - pos_y), Vector(SELECT_W, h), Color(SELECT_CLR), LAYER_GUI); - context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y + h), Vector(w, SELECT_W), Color(SELECT_CLR), LAYER_GUI); - context.draw_filled_rect(Vector(selection.x1 - pos_x, selection.y1 - pos_y), Vector(SELECT_W, h), Color(SELECT_CLR), LAYER_GUI); - } - } +sector = sector_; +/* Load sector stuff */ - /* draw button bar */ - context.draw_filled_rect(Vector(screen->w - 64, 0), Vector(64, screen->h), Color(50, 50, 50,255), LAYER_GUI); +sector->update_game_objects(); - if(le_current.IsTile()) +foregrounds = solids = backgrounds = 0; +/* Point foregrounds, backgrounds, solids to its layer */ +for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); i++) { -// le_level->get_sector("main")->solids->draw(context); + BadGuy* badguy = dynamic_cast (*i); + if(badguy) + badguy->activate(LEFT); -/*screen->w - 32, screen->h - 32, le_current.tile); - if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0) - TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);*/ - } -#if 0 // XXX FIXME TODO: Do we have a new solution for draw_on_screen()? - if(le_current.IsObject() && MouseCursor::current() != mouse_select_object) - { - le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32); - le_current.obj->draw_on_screen(cursor_x,cursor_y); + TileMap* tilemap = dynamic_cast (*i); + if(tilemap) + { + if(tilemap->get_layer() == LAYER_FOREGROUNDTILES) + foregrounds = tilemap; + else if(tilemap->get_layer() == LAYER_TILES) + solids = tilemap; + else if(tilemap->get_layer() == LAYER_BACKGROUNDTILES) + backgrounds = tilemap; + } } -#endif - if(mouse_select_object && selected_game_object != NULL) +if(!foregrounds) { - fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,selected_game_object->base.width,3,255,0,0,255); - fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255); - fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y-pos_y+selected_game_object->base.height,selected_game_object->base.width,3,255,0,0,255); - fillrect(selected_game_object->base.x-pos_x+selected_game_object->base.width,selected_game_object->base.y-pos_y,3,selected_game_object->base.height,255,0,0,255); + TileMap* tilemap = new TileMap(LAYER_FOREGROUNDTILES, false, solids->get_width(), solids->get_height()); + sector->add_object(tilemap); + sector->update_game_objects(); } - - if(le_level != NULL) +if(!backgrounds) { - le_save_level_bt->draw(context); - le_exit_bt->draw(context); - le_test_level_bt->draw(context); - le_next_level_bt->draw(context); - le_previous_level_bt->draw(context); - le_rubber_bt->draw(context); - if(le_selection_mode == SQUARE) - le_select_mode_one_bt->draw(context); - else if(le_selection_mode == CURSOR) - le_select_mode_two_bt->draw(context); - le_settings_bt->draw(context); - le_move_right_bt->draw(context); - le_move_left_bt->draw(context); - le_move_up_bt->draw(context); - le_move_down_bt->draw(context); - le_tilegroup_bt->draw(context); - le_objects_bt->draw(context); - if(!cur_tilegroup.empty()) - tilegroups_map[cur_tilegroup]->draw(context); - else if(!cur_objects.empty()) - { - objects_map[cur_objects]->draw(context); - } - - le_tilemap_panel->draw(context); - - if(!cur_objects.empty()) - { - le_object_select_bt->draw(context); - le_object_properties_bt->draw(context); - } + TileMap* tilemap = new TileMap(LAYER_BACKGROUNDTILES, false, solids->get_width(), solids->get_height()); + sector->add_object(tilemap); + sector->update_game_objects(); + } - 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), LEFT_ALLIGN, LAYER_GUI); +char str[64]; +sprintf(str, "%i", solids->get_width()); +settings_menu->get_item_by_id(MN_ID_WIDTH).change_input(str); +sprintf(str, "%i", solids->get_height()); +settings_menu->get_item_by_id(MN_ID_HEIGHT).change_input(str); +} - if(!le_help_shown) - context.draw_text(white_small_text, "F1 for Help", Vector(10, 430), LEFT_ALLIGN, LAYER_GUI); +void LevelEditor::save_level() +{ +level.save(level_filename); +level_changed = false; +} - if(display_level_info.check()) - context.draw_text(white_text, le_level->name.c_str(), Vector(screen->w/2, 0), CENTER_ALLIGN, LAYER_GUI); - } - else +void LevelEditor::test_level() +{ +if(level_changed) { - if(!Menu::current()) - context.draw_text(white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", Vector(10, 430), LEFT_ALLIGN, LAYER_GUI); - else - context.draw_text(white_small_text, "No Level Subset loaded", Vector(10, 430), LEFT_ALLIGN, LAYER_GUI); + if(confirm_dialog(NULL, _("Level not saved. Wanna to?"))) + save_level(); + else + return; } +GameSession session(level_filename, ST_GL_TEST); +session.run(); +// player_status.reset(); +sound_manager->halt_music(); } -void LevelEditor::drawlevel(DrawingContext& context) -{ -// unsigned int y,x; -// Uint8 a; +void LevelEditor::change(int x, int y, int newtile, int layer) +{ // find the tilemap of the current layer, and then change the tile +if(x < 0 || (unsigned int)x > sector->solids->get_width() || + y < 0 || (unsigned int)y > sector->solids->get_height()) + return; - /* Draw the real background */ - le_level->get_sector("main")->background->draw(context); +level_changed = true; - if(le_current.IsTile()) +if(newtile < 0) // add object { -//le_level->get_sector("main")->solids->draw(context); -/* - Tile::draw(cursor_x-pos_x, cursor_y-pos_y,le_current.tile,128); - if(!TileManager::instance()->get(le_current.tile)->images.empty()) - fillrect(cursor_x-pos_x,cursor_y-pos_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);*/ + // remove an active tile or object that might be there + change(x, y, 0, LAYER_TILES); + + if(newtile == OBJ_TRAMPOLINE) + sector->add_object(new Trampoline(x*32, y*32)); + else if(newtile == OBJ_FLYING_PLATFORM) + sector->add_object(new FlyingPlatform(x*32, y*32)); + else if(newtile == OBJ_DOOR) + sector->add_object(new Door(x*32, y*32)); + else + sector->add_object(new BadGuy(BadGuyKind((-newtile)-1), x*32, y*32)); + + sector->update_game_objects(); } -#if 0 // XXX FIXME TODO: Do we have a new solution for move_to()? - if(le_current.IsObject()) +else if(cur_layer == LAYER_FOREGROUNDTILES) + foregrounds->change(x, y, newtile); +else if(cur_layer == LAYER_TILES) { - le_current.obj->move_to(cursor_x, cursor_y); - } -#endif - - /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */ - -le_level->get_sector("main")->solids->draw(context); - -// FIXME: make tiles to be drawn semi-transparent when not selected -#if 0 - for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_level->get_section("main")->height; ++y) - for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x) + // remove a bad guy if it's there + for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i < sector->gameobjects.end(); i++) { + BadGuy* badguy = dynamic_cast (*i); + if(badguy) + if(badguy->base.x == x*32 && badguy->base.y == y*32) + sector->gameobjects.erase(i); + Trampoline* trampoline = dynamic_cast (*i); + if(trampoline) + if(trampoline->base.x == x*32 && trampoline->base.y == y*32) + sector->gameobjects.erase(i); + FlyingPlatform* flying_platform = dynamic_cast (*i); + if(flying_platform) + if(flying_platform->base.x == x*32 && flying_platform->base.y == y*32) + sector->gameobjects.erase(i); + Door* door = dynamic_cast (*i); + if(door) + if(door->get_area().x == x*32 && door->get_area().y == y*32) + sector->gameobjects.erase(i); + } + sector->update_game_objects(); + solids->change(x, y, newtile); + } +else if(cur_layer == LAYER_BACKGROUNDTILES) + backgrounds->change(x, y, newtile); +} - if(active_tm == TM_BG) - a = 255; - else - a = 128; - - Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), - le_level->bg_tiles[ (y + (int)(pos_y / 32)) * le_level->get_sector("main")->solids->get_width() + - (x + (int)(pos_x / 32))],a); +void LevelEditor::show_help() +{ +DrawingContext context; + +bool show_grid_t = show_grid; +show_grid = false; +mouse_cursor->set_state(MC_HIDE); + + +char str[1024]; +char *text1[] = { + _("This is the built-in level editor. It's aim is to be intuitive\n" + "and simple to use, so it should be pretty straight forward.\n" + "\n" + "To open a level, first you'll have to select a level subset from\n" + "the menu (or create your own).\n" + "A level subset is basically a collection of levels.\n" + "They can then be played from the Contrib menu.\n" + "\n" + "To access the menu from the level editor, just press Esc.\n" + "\n" + "You are currently looking to the level, to scroll it, just\n" + "press the right mouse button and drag the mouse. It will move like\n" + "a strategy game.\n" + "You can also use the arrow keys and Page Up/Down.\n" + "\n" + "'+' and '-' keys can be used to zoom in/out the level.\n" + "\n" + "You probably already noticed those floating group of buttons.\n" + "Each one serves a different purpose. To select a certain button\n" + "just press the Left mouse button on it. A few buttons have key\n" + "shortcuts, you can know it by pressing the Right mouse button on\n" + "it. That will also show what that button does.\n" + "Group of buttons can also be move around by just dragging them,\n" + "while pressing the Left mouse button.\n" + "\n" + "Let's learn a bit of what each group of buttons do, shall we?\n" + "\n" + "To starting putting tiles and objects around use the bigger gropup\n" + "of buttons. Each button is a different tile. To put it on the level,\n" + "just press it and then left click in the level.\n" + "You can also copy tiles from the level by using the middle mouse button.\n" + "Use the mouse wheel to scroll that group of buttons. You will find\n" + "enemies and game objects in the bottom.\n") + }; + +char *text2[] = { + _("The Foreground/Interactive/Background buttons may be used to\n" + "see and edit the respective layer. Level's have three tiles layers:\n" + "Foreground - tiles are drawn in top of everything and have no contact\n" + "with the player.\n" + "Interactive - these are the tiles that have contact with the player.\n" + "Background - tiles are drawn in bottom of everything and have no contact\n" + "with the player.\n" + "The unselected layers will be drawn semi-transparently.\n" + "\n" + "At last, but not least, the group of buttons that's left serves\n" + "to do related actions with the level.\n" + "From left to right:\n" + "Mini arrows - can be used to choose other sectors.\n" + "Sectors are mini-levels, so to speak, that can be accessed using a door.\n" + "Big arrows - choose other level in the same level subset.\n" + "Diskette - save the level\n" + "Tux - test the level\n" + "Tools - set a few settings for the level, incluiding resizing it.\n" + "\n" + "We have reached the end of this Howto.\n" + "\n" + "Don't forget to send us a few cool levels. :)\n" + "\n" + "Enjoy,\n" + " SuperTux development team\n" + "\n" + "ps: If you are looking for something more powerfull, you can give it a\n" + "try to FlexLay. FlexLay is a level editor that supports several games,\n" + "including SuperTux. It is an independent project.\n" + "Webpage: http://pingus.seul.org/~grumbel/flexlay/") + }; + +char **text[] = { text1, text2 }; + + +bool done; +for(unsigned int i = 0; i < sizeof(text) / sizeof(text[0]); i++) + { + draw(context); - if(active_tm == TM_IA) - a = 255; - else - a = 128; + context.draw_text(blue_text, _("- Level Editor's Help -"), Vector(screen->w/2, 60), CENTER_ALLIGN, LAYER_GUI); - Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), - le_level->ia_tiles[ (y + (int)(pos_y / 32)) * le_level->get_section("main")->width + - (x + (int)(pos_x / 32))],a); + context.draw_text(white_small_text, *text[i], Vector(20, 120), LEFT_ALLIGN, LAYER_GUI); - - if(active_tm == TM_FG) - a = 255; - else - a = 128; + sprintf(str,_("Press any key to continue - Page %d/%d"), i+1, sizeof(text) / sizeof(text[0])); + context.draw_text(gold_text, str, Vector(screen->w/2, screen->h-60), CENTER_ALLIGN, LAYER_GUI); - Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), - le_level->fg_tiles[ (y + (int)(pos_y / 32)) * le_level->get_sector("main")->solids->get_width() + - (x + (int)(pos_x / 32))],a); + context.do_drawing(); - /* draw whats inside stuff when cursor is selecting those */ - /* (draw them all the time - is this the right behaviour?) */ - Tile* edit_image = TileManager::instance()->get( - le_level->ia_tiles - [ (y + (int)(pos_y / 32)) * le_level->get_section("main")->width + (x + (int)(pos_x / 32))]); - if(edit_image && !edit_image->editor_images.empty()) - edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32)); + done = false; - } -#endif - /* Draw the Bad guys: */ - for (std::vector::iterator it = le_level->get_sector("main")->gameobjects.begin(); - it != le_level->get_sector("main")->gameobjects.end(); ++it) - { - BadGuy* badguy = dynamic_cast (*it); - if(badguy == 0) - continue; - - /* to support frames: img_bsod_left[(frame / 5) % 4] */ - badguy->draw(context); - } - - /* Draw the player: */ - /* for now, the position is fixed at (100, 240) */ -// largetux.walk_right->draw(context, Vector(100 - pos_x, 240 - pos_y), LAYER_OBJECTS-1); -} - -void LevelEditor::change_object_properties(GameObject *pobj) -{ - DrawingContext context; - - Menu* object_properties_menu = new Menu(); - bool loop = true; - - std::string type = typeid(pobj).name(); - object_properties_menu->additem(MN_LABEL, type + " Properties",0,0); - object_properties_menu->additem(MN_HL,"",0,0); - - BadGuy* pbad = dynamic_cast(pobj); - if(pobj != 0) - { - object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1); - for(int i = 0; i < NUM_BadGuyKinds; ++i) + while(!done) { - object_properties_menu->get_item_by_id(1).list.first.insert( - badguykind_to_string(static_cast(i))); - if(pbad->kind == i) - object_properties_menu->get_item_by_id(1).list.second = object_properties_menu->get_item_by_id(1).list.first.find(badguykind_to_string(static_cast(i))); + done = wait_for_event(event); + SDL_Delay(50); } - object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2); } - object_properties_menu->additem(MN_HL,"",0,0); - object_properties_menu->additem(MN_ACTION,"Ok",0,0,3); - - Menu::set_current(object_properties_menu); - - while(loop) - { - SDL_Event event; - - while (SDL_PollEvent(&event)) - { - object_properties_menu->event(event); - } - - //cap_screen->draw(0,0); - - object_properties_menu->draw(context); - object_properties_menu->action(); - - switch (object_properties_menu->check()) - { - case 3: - { - BadGuy* pbad = dynamic_cast(pobj); - if(pbad != 0) { - BadGuy* pbad = dynamic_cast(pobj); - pbad->kind = badguykind_from_string((*object_properties_menu->get_item_by_id(1).list.second)); - pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled; - } - loop = false; - break; - } - default: - break; - } - - if(Menu::current() == NULL) - loop = false; - - mouse_cursor->draw(context); -// context.draw_filled_rect(); - SDL_Delay(25); - } - - //delete cap_screen; - Menu::set_current(0); - delete object_properties_menu; -} - - -void LevelEditor::checkevents() -{ - SDLKey key; - SDLMod keymod; - Button* pbutton; - int x,y; - - keymod = SDL_GetModState(); - - while(SDL_PollEvent(&event)) - { - if (Menu::current()) - { - Menu::current()->event(event); - if(!le_level && !Menu::current()) - Menu::set_current(leveleditor_menu); - } - else - { - mouse_cursor->set_state(MC_NORMAL); - - /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/ - if(event.type == SDL_KEYDOWN - || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) - && (event.motion.x > 0 - && event.motion.x < screen->w - 64 && - event.motion.y > 0 && event.motion.y < screen->h))) - { - switch(event.type) - { - case SDL_KEYDOWN: // key pressed - key = event.key.keysym.sym; - switch(key) - { - case SDLK_ESCAPE: - Menu::set_current(leveleditor_menu); - break; - case SDLK_F1: - if(le_level != NULL) - showhelp(); - break; - case SDLK_HOME: - cursor_x = 0; - pos_x = cursor_x; - break; - case SDLK_END: - cursor_x = (le_level->get_sector("main")->solids->get_width() * 32) - 32; - pos_x = cursor_x; - break; - case SDLK_F9: - le_show_grid = !le_show_grid; - break; - default: - break; - } - break; - case SDL_MOUSEBUTTONDOWN: - if(event.button.button == SDL_BUTTON_LEFT) - { - le_mouse_pressed[LEFT] = true; - - selection.x1 = event.motion.x + pos_x; - selection.y1 = event.motion.y + pos_y; - selection.x2 = event.motion.x + pos_x; - selection.y2 = event.motion.y + pos_y; - } - else if(event.button.button == SDL_BUTTON_RIGHT) - { - le_mouse_pressed[RIGHT] = true; - } - break; - case SDL_MOUSEBUTTONUP: - if(event.button.button == SDL_BUTTON_LEFT) - { - le_mouse_pressed[LEFT] = false; - le_mouse_clicked[LEFT] = true; - } - else if(event.button.button == SDL_BUTTON_RIGHT) - { - le_mouse_pressed[RIGHT] = false; - le_mouse_clicked[RIGHT] = true; - } - break; - case SDL_MOUSEMOTION: - - if(!Menu::current()) - { - x = event.motion.x; - y = event.motion.y; - - if(le_current.IsTile()) - { - cursor_x = ((int)(pos_x + x) / 32) * 32; - cursor_y = ((int)(pos_y + y) / 32) * 32; - } - else - { - cursor_x = x; - cursor_y = y; - } - - if(le_mouse_pressed[LEFT]) - { - selection.x2 = x + pos_x; - selection.y2 = y + pos_y; - } - - if(le_mouse_pressed[RIGHT]) - { - pos_x += -1 * event.motion.xrel; - pos_y += -1 * event.motion.yrel; - } - } - break; - default: - break; - } - } - else if(event.type == SDL_QUIT) /* window closing */ - { - done = 1; - } - } - - if(le_level != NULL) - { - if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > screen->w-64 && event.motion.x < screen->w && - event.motion.y > 0 && event.motion.y < screen->h))) - { - le_mouse_pressed[LEFT] = false; - le_mouse_pressed[RIGHT] = false; - - if(!Menu::current()) - { - /* Check for button events */ - le_test_level_bt->event(event); - if(le_test_level_bt->get_state() == BUTTON_CLICKED) - testlevel(); - le_save_level_bt->event(event); - if(le_save_level_bt->get_state() == BUTTON_CLICKED) - le_level->save(le_level_subset->name.c_str()); - le_exit_bt->event(event); - if(le_exit_bt->get_state() == BUTTON_CLICKED) - { - Menu::set_current(leveleditor_menu); - } - le_next_level_bt->event(event); - if(le_next_level_bt->get_state() == BUTTON_CLICKED) - { - if(le_levelnb < le_level_subset->get_num_levels()) - { - goto_level(le_levelnb+1); - } - else - { - Level new_lev; - char str[1024]; - sprintf(str,"Level %d doesn't exist. Create it?",le_levelnb+1); - Surface* surf = new Surface(le_level->get_sector("main")->background->get_image(), false); - if(confirm_dialog(surf, str)) - { - 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) - delete surf; - } - } - le_previous_level_bt->event(event); - if(le_previous_level_bt->get_state() == BUTTON_CLICKED) - { - if(le_levelnb > 1) - goto_level(le_levelnb -1); - } - le_rubber_bt->event(event); - if(le_rubber_bt->get_state() == BUTTON_CLICKED) - le_current.Tile(0); - - if(!cur_objects.empty()) - { - le_object_select_bt->event(event); - if(le_object_select_bt->get_state() == BUTTON_CLICKED) - { - MouseCursor::set_current(mouse_select_object); - } - - le_object_properties_bt->event(event); - if(le_object_properties_bt->get_state() == BUTTON_CLICKED) - { - change_object_properties(selected_game_object); - } - } - - - if(le_selection_mode == SQUARE) - { - le_select_mode_one_bt->event(event); - if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED) - le_selection_mode = CURSOR; - } - else - { - le_select_mode_two_bt->event(event); - if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED) - le_selection_mode = SQUARE; - } - ButtonPanelMap::iterator it; - le_tilegroup_bt->event(event); - switch (le_tilegroup_bt->get_state()) - { - case BUTTON_CLICKED: - Menu::set_current(select_tilegroup_menu); - select_tilegroup_menu_effect.start(200); - select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5); - break; - case BUTTON_WHEELUP: - if(cur_tilegroup.empty()) - { - cur_tilegroup = tilegroups_map.begin()->first; - } - else - { - it = tilegroups_map.find(cur_tilegroup); - if((++it) == tilegroups_map.end()) - { - cur_tilegroup = tilegroups_map.begin()->first; - } - else - { - cur_tilegroup = (*it).first; - } - } - - cur_objects = ""; - break; - case BUTTON_WHEELDOWN: - it = tilegroups_map.find(cur_tilegroup); - if(it == tilegroups_map.begin()) - { - cur_tilegroup = tilegroups_map.rbegin()->first; - cur_objects = ""; - break; - } - if(--it != --tilegroups_map.begin()) - cur_tilegroup = (*it).first; - else - cur_tilegroup = tilegroups_map.rbegin()->first; - - cur_objects = ""; - break; - default: - break; - } - - le_objects_bt->event(event); - switch (le_objects_bt->get_state()) - { - case BUTTON_CLICKED: - Menu::set_current(select_objects_menu); - select_objects_menu_effect.start(200); - select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5); - break; - case BUTTON_WHEELUP: - it = objects_map.find(cur_objects); - if(it == objects_map.end()) - { - cur_objects = objects_map.begin()->first; - cur_tilegroup = ""; - break; - } - if(++it != objects_map.end()) - cur_objects = (*it).first; - else - cur_objects = objects_map.begin()->first; - - cur_tilegroup = ""; - break; - case BUTTON_WHEELDOWN: - it = objects_map.find(cur_objects); - if(it == objects_map.begin()) - { - cur_objects = objects_map.rbegin()->first; - cur_tilegroup = ""; - break; - } - if(--it != --objects_map.begin()) - cur_objects = (*it).first; - else - cur_objects = objects_map.rbegin()->first; - - cur_tilegroup = ""; - break; - break; - default: - break; - } - - le_settings_bt->event(event); - if(le_settings_bt->get_state() == BUTTON_CLICKED) - { - update_level_settings_menu(); - Menu::set_current(level_settings_menu); - } - if(!cur_tilegroup.empty()) - { - if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL) - { - if(pbutton->get_state() == BUTTON_CLICKED) - { - le_current.Tile(pbutton->get_tag()); - } - } - } - else if(!cur_objects.empty()) - { - if((pbutton = objects_map[cur_objects]->event(event)) != NULL) - { - if(pbutton->get_state() == BUTTON_CLICKED) - { -#if 0 // TODO FIXME XXX: New solution for this? - le_current.Object(pbutton->get_drawable()); -#endif - } - } - } - - if((pbutton = le_tilemap_panel->event(event)) != NULL) - { - if(pbutton->get_state() == BUTTON_CLICKED) - { - active_tm = pbutton->get_tag(); - } - } - } - else - { - le_settings_bt->event(event); - if(le_settings_bt->get_state() == BUTTON_CLICKED) - { - Menu::set_current(0); - } - le_tilegroup_bt->event(event); - if(le_tilegroup_bt->get_state() == BUTTON_CLICKED) - { - Menu::set_current(0); - } - le_objects_bt->event(event); - if(le_objects_bt->get_state() == BUTTON_CLICKED) - { - Menu::set_current(0); - } - } - } - - if(!Menu::current() && !show_minimap) - { - if(le_mouse_pressed[LEFT]) - { - if(MouseCursor::current() != mouse_select_object) - { - if(le_current.IsTile()) - change(cursor_x, cursor_y, active_tm, le_current.tile); - } - } - else if(le_mouse_clicked[LEFT]) - { - if(MouseCursor::current() == mouse_select_object) - { - bool object_got_hit = false; - base_type cursor_base; - if(le_current.IsTile()) - { - cursor_base.x = cursor_x; - cursor_base.y = cursor_y; - } - else if(le_current.IsObject()) - { - cursor_base.x = cursor_x + pos_x; - cursor_base.y = cursor_y + pos_y; - } - cursor_base.width = 32; - cursor_base.height = 32; - - for(std::vector::iterator it = - le_level->get_sector("main")->gameobjects.begin(); - it != le_level->get_sector("main")->gameobjects.end(); ++it) { - MovingObject* mobj = dynamic_cast (*it); - if(!mobj) - continue; - - if(rectcollision(cursor_base, mobj->base)) - { - selected_game_object = mobj; - object_got_hit = true; - break; - } - } - - if(!object_got_hit) - { - selected_game_object = NULL; - le_object_properties_bt->set_active(false); - } - else - le_object_properties_bt->set_active(true); - - MouseCursor::set_current(mouse_cursor); - - } - else - { - // FIXME TODO -#if 0 -//FIXME: objects interactions with the level editor should have a major improvement - if(le_current.IsObject()) - { - le_level_changed = true; - BadGuy* pbadguy = dynamic_cast(le_current.obj); - - if(pbadguy) - { - Camera& camera = *le_level->get_sector("main")->camera; - - le_level->get_sector("main")->bad_guys.push_back( - new BadGuy(pbadguy->kind, - cursor_x + camera.get_translation().x, - cursor_y + camera.get_translation().y)); - le_level->get_sector("main")->gameobjects.push_back(le_level->get_sector("main")->bad_guys.back()); - } - } -#endif - - } - - le_mouse_clicked[LEFT] = false; - - } - } - } - } - if(!Menu::current()) - { - show_minimap = false; - - if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_TAB) - show_minimap = true; - - le_move_left_bt->event(event); - le_move_right_bt->event(event); - le_move_up_bt->event(event); - le_move_down_bt->event(event); - switch(le_move_left_bt->get_state()) - { - case BUTTON_PRESSED: - pos_x -= KEYBOARD_SPEED; - show_minimap = true; - break; - case BUTTON_HOVER: - pos_x -= MOUSE_SPEED; - show_minimap = true; - break; - case BUTTON_CLICKED: - show_minimap = true; - break; - default: - break; - } - - switch(le_move_right_bt->get_state()) - { - case BUTTON_PRESSED: - pos_x += KEYBOARD_SPEED; - show_minimap = true; - break; - case BUTTON_HOVER: - pos_x += MOUSE_SPEED; - show_minimap = true; - break; - case BUTTON_CLICKED: - show_minimap = true; - break; - default: - break; - } - - switch(le_move_up_bt->get_state()) - { - case BUTTON_PRESSED: - pos_y -= KEYBOARD_SPEED; - show_minimap = true; - break; - case BUTTON_HOVER: - pos_y -= MOUSE_SPEED; - show_minimap = true; - break; - case BUTTON_CLICKED: - show_minimap = true; - break; - default: - break; - } - - switch(le_move_down_bt->get_state()) - { - case BUTTON_PRESSED: - pos_y += KEYBOARD_SPEED; - show_minimap = true; - break; - case BUTTON_HOVER: - pos_y += MOUSE_SPEED; - show_minimap = true; - break; - case BUTTON_CLICKED: - show_minimap = true; - break; - default: - break; - } - - /* checking if pos_x and pos_y is within the limits... */ - if((unsigned)pos_x > (le_level->get_sector("main")->solids->get_width() * 32 + 32*2) - screen->w) - pos_x = (le_level->get_sector("main")->solids->get_width() * 32 + 32*2) - screen->w; - if(pos_x < 0) - pos_x = 0; - - if((unsigned)pos_y > (le_level->get_sector("main")->solids->get_height() * 32) - screen->h) - pos_y = (le_level->get_sector("main")->solids->get_height() * 32) - screen->h; - if(pos_y < 0) - pos_y = 0; - } -} - -void LevelEditor::highlight_selection() -{ - int x1, x2, y1, y2; - - if(selection.x1 < selection.x2) - { - x1 = selection.x1; - x2 = selection.x2; - } - else - { - x1 = selection.x2; - x2 = selection.x1; - } - if(selection.y1 < selection.y2) - { - y1 = selection.y1; - y2 = selection.y2; - } - else - { - y1 = selection.y2; - y2 = selection.y1; - } - - x1 /= 32; - x2 /= 32; - y1 /= 32; - y2 /= 32; - - fillrect(x1*32-pos_x, y1*32-pos_y,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103); -} - -void LevelEditor::change(float x, float y, int tm, unsigned int c) -{ - if(le_level != NULL) - { - int xx,yy; - int x1, x2, y1, y2; - - le_level_changed = true; - - switch(le_selection_mode) - { - case CURSOR: - change(x,y,tm,c); - - base_type cursor_base; - cursor_base.x = x; - cursor_base.y = y; - cursor_base.width = 32; - cursor_base.height = 32; - - /* if there is a bad guy over there, remove it */ - // XXX TODO - for(std::vector::iterator it = le_level->get_sector("main")->gameobjects.begin(); - it != le_level->get_sector("main")->gameobjects.end(); ++it) { - BadGuy* badguy = dynamic_cast((*it)); - if (badguy) - { - if(rectcollision(cursor_base, badguy->base)) - { - delete (*it); - le_level->get_sector("main")->gameobjects.erase(std::remove(le_level->get_sector("main")->gameobjects.begin(), - le_level->get_sector("main")->gameobjects.end(), *it), - le_level->get_sector("main")->gameobjects.end()); - break; - } - } - } - - break; - case SQUARE: - if(selection.x1 < selection.x2) - { - x1 = selection.x1; - x2 = selection.x2; - } - else - { - x1 = selection.x2; - x2 = selection.x1; - } - if(selection.y1 < selection.y2) - { - y1 = selection.y1; - y2 = selection.y2; - } - else - { - y1 = selection.y2; - y2 = selection.y1; - } - - x1 /= 32; - x2 /= 32; - y1 /= 32; - y2 /= 32; - - /* if there is a bad guy over there, remove it */ - // TODO FIXME - for(std::vector::iterator it = le_level->get_sector("main")->gameobjects.begin(); - it != le_level->get_sector("main")->gameobjects.end(); ++it /* will be at end of loop */) - { - MovingObject* pmobject = dynamic_cast (*it); - if (pmobject) - { - if(pmobject->base.x/32 >= x1 && pmobject->base.x/32 <= x2 - && pmobject->base.y/32 >= y1 && pmobject->base.y/32 <= y2) - { - delete (*it); - le_level->get_sector("main")->gameobjects.erase(std::remove(le_level->get_sector("main")->gameobjects.begin(), le_level->get_sector("main")->gameobjects.end(), *it), le_level->get_sector("main")->gameobjects.end()); - continue; - } - else - { - ++it; - } - } - } - - for(xx = x1; xx <= x2; xx++) - for(yy = y1; yy <= y2; yy++) - { - change(xx*32, yy*32, tm, c); - - } - break; - default: - break; - } - } -} - -void LevelEditor::testlevel() -{ - //Make sure a time value is set when testing the level - if(le_level->time_left == 0) - le_level->time_left = 250; - - le_level->save("test.stl"); - - GameSession session("test.stl", ST_GL_TEST); - session.run(); - player_status.reset(); - - SoundManager::get()->halt_music(); - - Menu::set_current(NULL); -} - -void LevelEditor::showhelp() -{ - DrawingContext context; - - bool tmp_show_grid = le_show_grid; - SelectionMode temp_le_selection_mode = le_selection_mode; - le_selection_mode = NONE; - show_selections = true; - le_show_grid = false; - le_help_shown = true; - - SDL_Event event; - unsigned int done_; - char str[1024]; - char *text1[] = { - - " - Supertux level editor tutorial - ", - "", - "To make your map, click the ", - "tilegroup button and choose a ", - "tilegroup.", - "Pick a tile and simply hold down ", - "the left mouse button over the map", - "to \"paint\" your selection over", - "the screen.", - "", - "There are three layers for painting", - "tiles upon, Background layer,", - "the Interactive layer, and the", - "Foreground layer, which can be", - "toggled by the BkGrd, IntAct and", - "FrGrd buttons. The Foreground and", - "Background layers do not effect", - "Tux in the gameplay, but lie in", - "front of him or lie behind him in", - "his adventures.", - }; - - char *text2[] = { - - " - Supertux level editor tutorial - ", - "", - "The tiles placed on", - "the Interactive layer are those", - "which actually effect Tux in the", - "game.", - "", - "Click the objects menu to put ", - "bad guys and other objects in the", - "game. Unlike placing tiles, you", - "cannot \"paint\" enemies. Click", - "them onto the screen one at a time.", - "", - "To change the settings of your", - "level, click the button with the", - "screwdriver and wrench. From here", - "you can change the background,", - "music, length of the level,", - "and more." - }; - - char *text3[] = { - - " - Supertux level editor tutorial - ", - "", - "You may have more than one level.", - "Pressing the up and down buttons", - "above the button bar lets you", - "choose which one you are working on.", - "", - "If you would like to speed up your", - "level editing, a useful trick is", - "to learn the keyboard shortcuts.", - "They are easy to learn, just right-", - "click on the buttons.", - "", - "Have fun making levels! If you make", - "some good ones, send them to us on", - "the SuperTux mailing list!", - "- SuperTux team" - }; - - char **text[] = { text1, text2, text3 }; - - - for(int i = 0; i < 3; i++) - { - context.draw_gradient(Color(0,0,0), Color(255,255,255), LAYER_BACKGROUND0); - drawinterface(context); - - context.draw_text(blue_text, "- Help -", Vector(screen->w/2, 30), CENTER_ALLIGN, LAYER_GUI); - - for(unsigned int t = 0; t < sizeof(text[i])/sizeof(char *); t++) - context.draw_text(white_text, text[i][t], Vector(5, 80+(t*white_text->get_height())), LEFT_ALLIGN, LAYER_GUI); - - sprintf(str,"Press any key to continue - Page %d/%d?", i, static_cast(sizeof(text))); - context.draw_text(gold_text, str, Vector(0, 0), LEFT_ALLIGN, LAYER_GUI); - - context.do_drawing(); - - done_ = 0; - - while(done_ == 0) - { - done_ = wait_for_event(event); - SDL_Delay(50); - } - } - - show_selections = true; - le_show_grid = tmp_show_grid; - le_selection_mode = temp_le_selection_mode; - le_help_shown = false; +show_grid = show_grid_t; +mouse_cursor->set_state(MC_NORMAL); } diff --git a/src/leveleditor.h b/src/leveleditor.h index a63f78b70..50d8d0133 100644 --- a/src/leveleditor.h +++ b/src/leveleditor.h @@ -1,203 +1,149 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2003 Ricardo Cruz -// Copyright (C) 2003 Tobias Glaesser -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -/* leveleditor.h - A built-in level editor for SuperTux */ +/*************************************************************************** + leveleditor.h - built'in level editor + ------------------- + begin : June, 23 2004 + copyright : (C) 2004 by Ricardo Cruz + email : rick2@aeiou.pt + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ #ifndef SUPERTUX_LEVELEDITOR_H #define SUPERTUX_LEVELEDITOR_H +#include "SDL.h" + +#include +#include + #include "video/drawing_context.h" -#include "special/game_object.h" -#include "video/surface.h" +#include "special/timer.h" #include "level.h" #include "level_subset.h" -#include "special/moving_object.h" -#include "gui/button.h" -#include "gui/menu.h" using namespace SuperTux; -enum LevelEditorMainMenuIDs { - MNID_RETURNLEVELEDITOR, - MNID_SUBSETSETTINGS, - MNID_QUITLEVELEDITOR - }; +namespace SuperTux { +class ButtonGroup; +class Menu; +class Surface; +} + +class Sector; +class TileMap; + +enum { + MN_ID_RETURN, + MN_ID_LOAD_SUBSET, + MN_ID_QUIT, + + // settings menu ids: + MN_ID_NAME, + MN_ID_AUTHOR, + MN_ID_WIDTH, + MN_ID_HEIGHT, + MN_ID_APPLY_SETTINGS, -enum LevelEditorSubsetSettingsIDs { - MNID_SUBSETTITLE, - MNID_SUBSETDESCRIPTION, - MNID_SUBSETSAVECHANGES + // creating subset menu ids: + MN_ID_FILENAME_SUBSET, + MN_ID_TITLE_SUBSET, + MN_ID_DESCRIPTION_SUBSET, + MN_ID_CREATE_SUBSET }; - -enum LevelEditorSubsetNewIDs { - MNID_SUBSETNAME, - MNID_CREATESUBSET -}; -enum LevelEditorSettingsMenuIDs { - MNID_NAME, - MNID_AUTHOR, - MNID_SONG, - MNID_BGIMG, - MNID_PARTICLE, - MNID_LENGTH, - MNID_HEIGHT, - MNID_TIME, - MNID_GRAVITY, - MNID_BGSPEED, - MNID_TopRed, - MNID_TopGreen, - MNID_TopBlue, - MNID_BottomRed, - MNID_BottomGreen, - MNID_BottomBlue, - MNID_APPLY +enum { + BT_LEVEL_SAVE, + BT_LEVEL_TEST, + BT_LEVEL_SETUP, + + BT_NEXT_LEVEL, + BT_PREVIOUS_LEVEL, + BT_NEXT_SECTOR, + BT_PREVIOUS_SECTOR + }; + +enum { + OBJ_TRAMPOLINE = -100, + OBJ_FLYING_PLATFORM = -101, + OBJ_DOOR = -102 }; - class LevelEditor { public: LevelEditor(); ~LevelEditor(); - int run(char* filename = NULL); + void run(const std::string filename = ""); private: + void events(); + void action(); + void draw(DrawingContext& context); -// Functions -void newlevel(void); -void selectlevel(void); -void savelevel(); -void editlevel(void); -void testlevel(void); -void checkevents(void); -void unload_level(); - -/* own declerations */ -/* crutial ones (main loop) */ -void init_menus(); -int load_level_subset(const char *filename); -void drawlevel(DrawingContext& context); -void drawinterface(DrawingContext& context); -void change(float x, float y, int tm, unsigned int c); -void showhelp(); -void set_defaults(void); -void activate_bad_guys(void); -void goto_level(int levelnb); -void highlight_selection(); - -void drawminimap(); - -void apply_level_settings_menu(); -void update_subset_settings_menu(); -void save_subset_settings_menu(); -void update_level_settings_menu(); -void change_object_properties(GameObject *pobj); - -// structs -struct TileOrObject -{ - TileOrObject() : tile(0), obj(NULL) { is_tile = true; }; + void load_level_subset(std::string filename); + void load_level(std::string filename); + void load_level(int nb); + void load_sector(std::string name); + void load_sector(Sector* sector); - void Tile(unsigned int set_to) { tile = set_to; is_tile = true; } - void Object(GameObject* pobj) { obj = pobj; is_tile = false; } - //Returns true for a tile - bool IsTile() { return is_tile; }; - //Returns true for a GameObject - bool IsObject() { return !is_tile; }; + void save_level(); + void test_level(); + void setup_level(); + void show_help(); - void Init() { tile = 0; obj = NULL; is_tile = true; }; + void change(int x, int y, int newtile, int layer); - bool is_tile; //true for tile (false for object) - unsigned int tile; - GameObject* obj; -}; + void load_buttons_gfx(); + void free_buttons_gfx(); -struct square -{ - int x1, y1, x2, y2; -}; + Level level; + std::string level_filename; + + Sector* sector; // current sector + TileMap *solids, *foregrounds, *backgrounds; + std::string sector_name; + + std::set level_subsets; + LevelSubset level_subset; + int level_nb; + + Menu* main_menu; + Menu* subset_menu; + Menu* create_subset_menu; + Menu* settings_menu; + + bool left_button, middle_button; + bool done; + bool show_grid; + + Vector scroll; + float zoom; + + SDL_Event event; + Timer frame_timer; + Timer level_name_timer; + + Surface *img_background_bt, *img_foreground_bt, *img_interactive_bt; + Surface *img_save_level_bt, *img_setup_level_bt, *img_test_level_bt; + Surface *img_rubber_bt; + Surface *img_previous_level_bt, *img_next_level_bt, *img_previous_sector_bt, *img_next_sector_bt; + + ButtonGroup *tiles_board, *tiles_layer, *level_options; + int cur_layer; + + std::vector > selection; + Vector selection_ini, selection_end; -/* selection modes */ -enum SelectionMode { CURSOR, SQUARE, NONE }; - -// variables -/* leveleditor internals */ -std::set level_subsets; -bool le_level_changed; /* if changes, ask for saving, when quiting*/ -bool show_minimap; -bool show_selections; -bool le_help_shown; -int pos_x, pos_y, cursor_x, cursor_y; -int le_levelnb; -Level* le_level; -LevelSubset* le_level_subset; -int le_show_grid; -int le_frame; -Surface* le_selection; -int done; -TileOrObject le_current; -bool le_mouse_pressed[2]; -bool le_mouse_clicked[2]; -Button* le_save_level_bt; -Button* le_exit_bt; -Button* le_test_level_bt; -Button* le_next_level_bt; -Button* le_previous_level_bt; -Button* le_move_right_bt; -Button* le_move_left_bt; -Button* le_move_up_bt; -Button* le_move_down_bt; -Button* le_rubber_bt; -Button* le_select_mode_one_bt; -Button* le_select_mode_two_bt; -Button* le_settings_bt; -Button* le_tilegroup_bt; -Button* le_objects_bt; -Button* le_object_select_bt; -Button* le_object_properties_bt; -ButtonPanel* le_tilemap_panel; -int active_tm; -Menu* leveleditor_menu; -Menu* subset_load_menu; -Menu* subset_new_menu; -Menu* subset_settings_menu; -Menu* level_settings_menu; -Menu* select_tilegroup_menu; -Menu* select_objects_menu; -Timer select_tilegroup_menu_effect; -Timer select_objects_menu_effect; -Timer display_level_info; -typedef std::map ButtonPanelMap; -ButtonPanelMap tilegroups_map; -ButtonPanelMap objects_map; -std::string cur_tilegroup; -std::string cur_objects; -MouseCursor* mouse_select_object; -MovingObject* selected_game_object; - -square selection; -SelectionMode le_selection_mode; -SDL_Event event; + bool level_changed; }; -#endif /*SUPERTUX_LEVELEDITOR_H*/ +#endif diff --git a/src/title.cpp b/src/title.cpp index 77b00a99f..98be258bf 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -114,7 +114,7 @@ void generate_contrib_menu() for (std::set::iterator it = level_subsets.begin(); it != level_subsets.end(); ++it) { LevelSubset* subset = new LevelSubset(); - subset->load((*it).c_str()); + subset->load(*it); contrib_menu->additem(MN_GOTO, subset->title, 0, contrib_subset_menu, i); contrib_subsets.push_back(subset); ++i;