0b147ceee2d6b13bdda205cc2b599ecac9670887
[supertux.git] / src / leveleditor.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2003 Ricardo Cruz <rick2@aeiou.pt>
5 //  Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 #include <map>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <SDL.h>
29 #include <SDL_image.h>
30 #include "leveleditor.h"
31
32 #include "screen.h"
33 #include "defines.h"
34 #include "globals.h"
35 #include "setup.h"
36 #include "menu.h"
37 #include "level.h"
38 #include "gameloop.h"
39 #include "badguy.h"
40 #include "scene.h"
41 #include "button.h"
42 #include "tile.h"
43 #include "resources.h"
44 #include "music_manager.h"
45
46 /* definitions to aid development */
47
48 /* definitions that affect gameplay */
49 #define KEY_CURSOR_SPEED 32
50 #define KEY_CURSOR_FASTSPEED 64
51
52 /* when pagedown/up pressed speed:*/
53 #define PAGE_CURSOR_SPEED 13*32
54
55 #define MOUSE_LEFT_MARGIN 80
56 #define MOUSE_RIGHT_MARGIN (560-32)
57 /* right_margin should noticed that the cursor is 32 pixels,
58    so it should subtract that value */
59 #define MOUSE_POS_SPEED 20
60
61 /* look */
62 #define SELECT_W 2 // size of the selections lines
63 #define SELECT_CLR 0, 255, 0, 255  // lines color (R, G, B, A)
64
65 /* own declerations */
66 /* crutial ones (main loop) */
67 int le_init();
68 void le_quit();
69 void le_drawlevel();
70 void le_drawinterface();
71 void le_checkevents();
72 void le_change(float x, float y, int tm, unsigned int c);
73 void le_testlevel();
74 void le_showhelp();
75 void le_set_defaults(void);
76 void le_activate_bad_guys(void);
77
78 void le_highlight_selection();
79
80 void apply_level_settings_menu();
81 void update_subset_settings_menu();
82 void save_subset_settings_menu();
83
84 static Level* le_current_level;
85
86 struct LevelEditorWorld
87 {
88   std::vector<BadGuy> bad_guys;
89   void arrays_free(void)
90   {
91     bad_guys.clear();
92   }
93
94   void add_bad_guy(float x, float y, BadGuyKind kind)
95   {
96     bad_guys.push_back(BadGuy(x,y,kind, false /* stay_on_platform */));
97   }
98
99   void activate_bad_guys()
100   {
101     for (std::vector<BadGuyData>::iterator i = le_current_level->badguy_data.begin();
102          i != le_current_level->badguy_data.end();
103          ++i)
104     {
105       add_bad_guy(i->x, i->y, i->kind);
106     }
107   }
108 };
109
110 struct TileOrObject
111 {
112   TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
113
114   void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
115   void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
116   //Returns true for a tile
117   bool IsTile() { return is_tile; };
118   //Returns true for a GameObject
119   bool IsObject() { return !is_tile; };
120
121   bool is_tile; //true for tile (false for object)
122   unsigned int tile;
123   GameObject* obj;
124 };
125
126 /* leveleditor internals */
127 static string_list_type level_subsets;
128 static bool le_level_changed;  /* if changes, ask for saving, when quiting*/
129 static int pos_x, cursor_x, cursor_y, fire;
130 static int le_level;
131 static LevelEditorWorld le_world;
132 static LevelSubset* le_level_subset;
133 static int le_show_grid;
134 static int le_frame;
135 static Surface* le_selection;
136 static int done;
137 static TileOrObject le_current;
138 static bool le_mouse_pressed[2];
139 static Button* le_save_level_bt;
140 static Button* le_exit_bt;
141 static Button* le_test_level_bt;
142 static Button* le_next_level_bt;
143 static Button* le_previous_level_bt;
144 static Button* le_move_right_bt;
145 static Button* le_move_left_bt;
146 static Button* le_rubber_bt;
147 static Button* le_select_mode_one_bt;
148 static Button* le_select_mode_two_bt;
149 static Button* le_settings_bt;
150 static Button* le_tilegroup_bt;
151 static Button* le_objects_bt;
152 static ButtonPanel* le_tilemap_panel;
153 static Menu* leveleditor_menu;
154 static Menu* subset_load_menu;
155 static Menu* subset_new_menu;
156 static Menu* subset_settings_menu;
157 static Menu* level_settings_menu;
158 static Menu* select_tilegroup_menu;
159 static Menu* select_objects_menu;
160 static Timer select_tilegroup_menu_effect;
161 static Timer select_objects_menu_effect;
162 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
163 static ButtonPanelMap tilegroups_map;
164 static ButtonPanelMap objects_map;
165 static std::string cur_tilegroup;
166 static std::string cur_objects;
167
168 static square selection;
169 static int le_selection_mode;
170 static SDL_Event event;
171 TileMapType active_tm;
172
173 void le_set_defaults()
174 {
175   if(le_current_level != NULL)
176   {
177     /* Set defaults: */
178
179     if(le_current_level->time_left == 0)
180       le_current_level->time_left = 255;
181   }
182 }
183
184 int leveleditor(int levelnb)
185 {
186   int last_time, now_time, i;
187
188   le_level = levelnb;
189   if(le_init() != 0)
190     return 1;
191
192   /* Clear screen: */
193
194   clearscreen(0, 0, 0);
195   updatescreen();
196
197   music_manager->halt_music();
198
199   while (SDL_PollEvent(&event))
200   {}
201
202   while(true)
203   {
204     last_time = SDL_GetTicks();
205     le_frame++;
206
207     le_checkevents();
208
209     if(Menu::current() == select_tilegroup_menu)
210     {
211       if(select_tilegroup_menu_effect.check())
212       {
213         select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
214                                        66,-0.5,0.5);
215       }
216       else
217         select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
218     }
219     else if(Menu::current() == select_objects_menu)
220     {
221       if(select_objects_menu_effect.check())
222       {
223         select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
224       }
225       else
226         select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
227     }
228
229     if(le_current_level != NULL)
230     {
231       /* making events results to be in order */
232       if(pos_x < 0)
233         pos_x = 0;
234       if(pos_x > (le_current_level->width * 32) - screen->w)
235         pos_x = (le_current_level->width * 32) - screen->w;
236
237       /* draw the level */
238       le_drawlevel();
239     }
240     else
241       clearscreen(0, 0, 0);
242
243     /* draw editor interface */
244     le_drawinterface();
245
246     Menu* menu = Menu::current();
247     if(menu)
248     {
249       menu->draw();
250       menu->action();
251
252       if(menu == leveleditor_menu)
253       {
254         switch (leveleditor_menu->check())
255         {
256         case MNID_RETURNLEVELEDITOR:
257           Menu::set_current(0);
258           break;
259         case MNID_SUBSETSETTINGS:
260           update_subset_settings_menu();
261           break;
262         case MNID_QUITLEVELEDITOR:
263           done = 1;
264           break;
265         }
266       }
267       else if(menu == level_settings_menu)
268       {
269         switch (level_settings_menu->check())
270         {
271         case MNID_APPLY:
272           apply_level_settings_menu();
273           Menu::set_current(NULL);
274           break;
275
276         default:
277           //show_menu = true;
278           break;
279         }
280       }
281       else if(menu == select_tilegroup_menu)
282       {
283         int it = -1;
284         switch (it = select_tilegroup_menu->check())
285         {
286         default:
287           if(it >= 0)
288           {
289             cur_tilegroup
290             = select_tilegroup_menu->get_item_by_id(it).text;
291             Menu::set_current(0);
292             cur_objects.clear();
293
294           }
295           break;
296         }
297       }
298       else if(menu == select_objects_menu)
299       {
300         int it = -1;
301         switch (it = select_objects_menu->check())
302         {
303         default:
304           if(it >= 0)
305           {
306             cur_objects = select_objects_menu->get_item_by_id(it).text;
307             cur_tilegroup.clear();
308
309             Menu::set_current(0);
310           }
311           break;
312         }
313       }
314       else if(menu == subset_load_menu)
315       {
316         switch (i = subset_load_menu->check())
317         {
318         case 0:
319           break;
320         default:
321           if(i >= 1)
322           {
323             le_level_subset->load(level_subsets.item[i-1]);
324             leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
325             le_level = 1;
326             le_world.arrays_free();
327             delete le_current_level;
328             le_current_level = new Level;
329             if(le_current_level->load(le_level_subset->name, le_level) != 0)
330             {
331               le_quit();
332               return 1;
333             }
334             le_set_defaults();
335             le_current_level->load_gfx();
336             le_world.activate_bad_guys();
337
338             Menu::set_current(NULL);
339           }
340           break;
341         }
342       }
343       else if(menu == subset_new_menu)
344       {
345         if(subset_new_menu->item[2].input[0] == '\0')
346           subset_new_menu->item[3].kind = MN_DEACTIVE;
347         else
348         {
349           subset_new_menu->item[3].kind = MN_ACTION;
350
351           switch (i = subset_new_menu->check())
352           {
353           case MNID_CREATESUBSET:
354             LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
355             le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
356             leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
357             le_level = 1;
358             le_world.arrays_free();
359             delete le_current_level;
360             le_current_level = new Level;
361             if(le_current_level->load(le_level_subset->name, le_level) != 0)
362             {
363               le_quit();
364               return 1;
365             }
366             le_set_defaults();
367             le_current_level->load_gfx();
368             le_world.activate_bad_guys();
369             subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
370             
371             Menu::set_current(subset_settings_menu);
372             break;
373           }
374         }
375       }
376       else if(menu == subset_settings_menu)
377       {
378         if(le_level_subset->title.compare(subset_settings_menu->get_item_by_id(MNID_TITLE).input) == 0 && le_level_subset->description.compare(subset_settings_menu->get_item_by_id(MNID_DESCRIPTION).input) == 0  )
379           subset_settings_menu->get_item_by_id(MNID_SAVE_CHANGES).kind = MN_DEACTIVE;
380         else
381           subset_settings_menu->get_item_by_id(MNID_SAVE_CHANGES).kind = MN_ACTION;
382
383         switch (i = subset_settings_menu->check())
384         {
385         case MNID_SAVE_CHANGES:
386           save_subset_settings_menu();
387           //FIXME:show_menu = true;
388           Menu::set_current(leveleditor_menu);
389           break;
390         }
391       }
392     }
393
394     mouse_cursor->draw();
395
396     if(done)
397     {
398       le_quit();
399       return 0;
400     }
401
402     ++global_frame_counter;
403
404     SDL_Delay(25);
405     now_time = SDL_GetTicks();
406     if (now_time < last_time + FPS)
407       SDL_Delay(last_time + FPS - now_time);    /* delay some time */
408
409     flipscreen();
410   }
411
412   return done;
413 }
414
415
416 void le_init_menus()
417 {
418   int i;
419
420   leveleditor_menu = new Menu();
421   subset_load_menu = new Menu();
422   subset_new_menu  = new Menu();
423   subset_settings_menu = new Menu();
424   level_settings_menu  = new Menu();
425   select_tilegroup_menu  = new Menu();
426   select_objects_menu = new Menu();
427
428   leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
429   leveleditor_menu->additem(MN_HL,"",0,0);
430   leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
431   leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
432   leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
433   leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
434   leveleditor_menu->additem(MN_HL,"",0,0);
435   leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
436
437   Menu::set_current(leveleditor_menu);
438
439   subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
440   subset_load_menu->additem(MN_HL, "", 0, 0);
441
442   for(i = 0; i < level_subsets.num_items; ++i)
443   {
444     subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
445   }
446   subset_load_menu->additem(MN_HL,"",0,0);
447   subset_load_menu->additem(MN_BACK,"Back",0,0);
448
449   subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
450   subset_new_menu->additem(MN_HL,"",0,0);
451   subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0);
452   subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
453   subset_new_menu->additem(MN_HL,"",0,0);
454   subset_new_menu->additem(MN_BACK,"Back",0,0);
455
456   subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
457   subset_settings_menu->additem(MN_HL,"",0,0);
458   subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0);
459   subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0);
460   subset_settings_menu->additem(MN_HL,"",0,0);
461   subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0);
462   subset_settings_menu->additem(MN_HL,"",0,0);
463   subset_settings_menu->additem(MN_BACK,"Back",0,0);
464
465   level_settings_menu->arrange_left = true;
466   level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
467   level_settings_menu->additem(MN_HL,"",0,0);
468   level_settings_menu->additem(MN_TEXTFIELD,"Name    ",0,0,MNID_NAME);
469   level_settings_menu->additem(MN_TEXTFIELD,"Author  ",0,0,MNID_AUTHOR);
470   level_settings_menu->additem(MN_STRINGSELECT,"Song    ",0,0,MNID_SONG);
471   level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
472   level_settings_menu->additem(MN_NUMFIELD,"Length ",0,0,MNID_LENGTH);
473   level_settings_menu->additem(MN_NUMFIELD,"Time   ",0,0,MNID_TIME);
474   level_settings_menu->additem(MN_NUMFIELD,"Gravity",0,0,MNID_GRAVITY);
475   level_settings_menu->additem(MN_NUMFIELD,"Top Red    ",0,0,MNID_TopRed);
476   level_settings_menu->additem(MN_NUMFIELD,"Top Green  ",0,0,MNID_TopGreen);
477   level_settings_menu->additem(MN_NUMFIELD,"Top Blue   ",0,0,MNID_TopBlue);
478   level_settings_menu->additem(MN_NUMFIELD,"Bottom Red ",0,0,MNID_BottomRed);
479   level_settings_menu->additem(MN_NUMFIELD,"Bottom Green",0,0,MNID_BottomGreen);
480   level_settings_menu->additem(MN_NUMFIELD,"Bottom Blue",0,0,MNID_BottomBlue);
481   level_settings_menu->additem(MN_HL,"",0,0);
482   level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
483
484   select_tilegroup_menu->arrange_left = true;
485   select_tilegroup_menu->additem(MN_LABEL,"Select Tilegroup",0,0);
486   select_tilegroup_menu->additem(MN_HL,"",0,0);
487   std::vector<TileGroup>* tilegroups = TileManager::tilegroups();
488   int tileid = 1;
489   for(std::vector<TileGroup>::iterator it = tilegroups->begin();
490       it != tilegroups->end(); ++it )
491   {
492     select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
493     tileid++;
494     tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
495     i = 0;
496
497     for(std::vector<int>::iterator sit = (*it).tiles.begin();
498         sit != (*it).tiles.end(); ++sit, ++i)
499     {
500       std::string imagefile = "/images/tilesets/" ;
501       imagefile += TileManager::instance()->get(*sit)->filenames[0];
502       Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
503                                   0, 0, 32, 32);
504       tilegroups_map[it->name]->additem(button, *sit);
505     }
506   }
507   select_tilegroup_menu->additem(MN_HL,"",0,0);
508
509   select_objects_menu->arrange_left = true;
510   select_objects_menu->additem(MN_LABEL,"Select Objects",0,0);
511   select_objects_menu->additem(MN_HL,"",0,0);
512   select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
513   objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
514
515   for(int i = 0; i < NUM_BadGuyKinds; ++i)
516   {
517     BadGuy bad_tmp(0,0,BadGuyKind(i),false);
518     objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
519     objects_map["BadGuys"]->manipulate_button(i)->set_game_object(new BadGuy(objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,BadGuyKind(i),false));
520   }
521
522   select_objects_menu->additem(MN_HL,"",0,0);
523
524 }
525
526 int le_init()
527 {
528   level_subsets = dsubdirs("/levels", "info");
529
530   le_level_subset = new LevelSubset;
531
532   active_tm = TM_IA;
533
534   le_show_grid = true;
535
536   /*  level_changed = NO;*/
537   fire = DOWN;
538   done = 0;
539   le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
540   le_level_changed = false;
541   le_current_level = NULL;
542
543   le_mouse_pressed[LEFT] = false;
544   le_mouse_pressed[RIGHT] = false;
545
546   le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
547
548   select_tilegroup_menu_effect.init(false);
549   select_objects_menu_effect.init(false);
550
551   /* Load buttons */
552   le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
553   le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F6,screen->w-32,32);
554   le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
555   le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
556   le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
557   le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
558   le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
559   le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
560   le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
561   le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
562   le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
563   le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
564   le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F7,screen->w-64,80);
565
566   le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
567   le_tilemap_panel->set_button_size(32,10);
568   le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_F4,0,0),TM_BG);
569   le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_F4,0,0),TM_IA);
570   le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_F4,0,0),TM_FG);
571
572   le_init_menus();
573
574   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
575
576   return 0;
577 }
578
579 void update_level_settings_menu()
580 {
581   char str[80];
582   int i;
583   
584   level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_current_level->name.c_str());
585   level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_current_level->author.c_str());
586   
587   string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
588   string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
589   string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
590   
591   if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_current_level->song_title.c_str())) != -1)
592     level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
593   if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_current_level->bkgd_image.c_str())) != -1)
594     level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
595   
596   sprintf(str,"%d",le_current_level->width);  
597   level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
598   sprintf(str,"%d",le_current_level->time_left);
599   level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
600   sprintf(str,"%2.0f",le_current_level->gravity);
601   level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
602   sprintf(str,"%d",le_current_level->bkgd_top.red);
603   level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
604   sprintf(str,"%d",le_current_level->bkgd_top.green);
605   level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
606   sprintf(str,"%d",le_current_level->bkgd_top.blue);
607   level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
608   sprintf(str,"%d",le_current_level->bkgd_bottom.red);
609   level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
610   sprintf(str,"%d",le_current_level->bkgd_bottom.green);
611   level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
612   sprintf(str,"%d",le_current_level->bkgd_bottom.blue);
613   level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
614 }
615
616 void update_subset_settings_menu()
617 {
618   subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
619   subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
620 }
621
622 void apply_level_settings_menu()
623 {
624   int i;
625   i = false;
626
627   le_current_level->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
628   le_current_level->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
629
630   if(le_current_level->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
631   {
632     le_current_level->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
633     i = true;
634   }
635
636   if(i)
637   {
638     le_current_level->load_gfx();
639   }
640
641   le_current_level->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
642
643   le_current_level->change_size(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
644   le_current_level->time_left = atoi(level_settings_menu->get_item_by_id(MNID_BGIMG).input);
645   le_current_level->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
646   le_current_level->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
647   le_current_level->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
648   le_current_level->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
649   le_current_level->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
650   le_current_level->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
651   le_current_level->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
652 }
653
654 void save_subset_settings_menu()
655 {
656   le_level_subset->title = subset_settings_menu->item[2].input;
657   le_level_subset->description = subset_settings_menu->item[3].input;
658   le_level_subset->save();
659 }
660
661 void le_goto_level(int levelnb)
662 {
663   le_world.arrays_free();
664
665   le_current_level->cleanup();
666   if(le_current_level->load(le_level_subset->name.c_str(), levelnb) != 0)
667   {
668     le_current_level->load(le_level_subset->name.c_str(), le_level);
669   }
670   else
671   {
672     le_level = levelnb;
673   }
674
675   le_set_defaults();
676
677   le_current_level->load_gfx();
678
679   le_world.activate_bad_guys();
680 }
681
682 void le_quit(void)
683 {
684   /*if(level_changed == true)
685     if(askforsaving() == CANCEL)
686       return;*/ //FIXME
687
688   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
689
690   delete le_selection;
691   delete leveleditor_menu;
692   delete subset_load_menu;
693   delete subset_new_menu;
694   delete subset_settings_menu;
695   delete level_settings_menu;
696   delete select_tilegroup_menu;
697   delete select_objects_menu;
698   delete le_save_level_bt;
699   delete le_exit_bt;
700   delete le_test_level_bt;
701   delete le_next_level_bt;
702   delete le_previous_level_bt;
703   delete le_move_right_bt;
704   delete le_move_left_bt;
705   delete le_rubber_bt;
706   delete le_select_mode_one_bt;
707   delete le_select_mode_two_bt;
708   delete le_settings_bt;
709   delete le_tilegroup_bt;
710   delete le_objects_bt;
711   delete le_tilemap_panel;
712
713   delete le_current_level;
714   le_current_level = 0;
715   delete le_level_subset;
716   le_level_subset = 0;
717
718   for(ButtonPanelMap::iterator i = tilegroups_map.begin();
719       i != tilegroups_map.end(); ++i)
720   {
721     delete i->second;
722   }
723   for(ButtonPanelMap::iterator i = objects_map.begin();
724       i != objects_map.end(); ++i)
725   {
726     delete i->second;
727   }
728 }
729
730 void le_drawinterface()
731 {
732   int x,y;
733   char str[80];
734
735   if(le_current_level != NULL)
736   {
737     /* draw a grid (if selected) */
738     if(le_show_grid)
739     {
740       for(x = 0; x < 19; x++)
741         fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
742       for(y = 0; y < 15; y++)
743         fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
744     }
745   }
746
747   if(le_selection_mode == CURSOR)
748     le_selection->draw( cursor_x - pos_x, cursor_y);
749   else if(le_selection_mode == SQUARE)
750   {
751     int w, h;
752     le_highlight_selection();
753     /* draw current selection */
754     w = selection.x2 - selection.x1;
755     h = selection.y2 - selection.y1;
756     fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
757     fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
758     fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
759     fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
760   }
761
762
763   /* draw button bar */
764   fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
765
766   if(le_current.IsTile())
767   {
768     Tile::draw(19 * 32, 14 * 32, le_current.tile);
769     if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
770       TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
771   }
772   
773   //if(le_current.IsObject())
774   //printf("");
775
776   if(le_current_level != NULL)
777   {
778     le_save_level_bt->draw();
779     le_exit_bt->draw();
780     le_test_level_bt->draw();
781     le_next_level_bt->draw();
782     le_previous_level_bt->draw();
783     le_rubber_bt->draw();
784     if(le_selection_mode == SQUARE)
785       le_select_mode_one_bt->draw();
786     else if(le_selection_mode == CURSOR)
787       le_select_mode_two_bt->draw();
788     le_settings_bt->draw();
789     le_move_right_bt->draw();
790     le_move_left_bt->draw();
791     le_tilegroup_bt->draw();
792     le_objects_bt->draw();
793     if(!cur_tilegroup.empty())
794       tilegroups_map[cur_tilegroup]->draw();
795     else if(!cur_objects.empty())
796     {
797       objects_map[cur_objects]->draw();
798     }
799
800     le_tilemap_panel->draw();
801
802     sprintf(str, "%d/%d", le_level,le_level_subset->levels);
803     white_text->drawf(str, -10, 16, A_RIGHT, A_TOP, 0);
804
805     white_small_text->draw("F1 for Help", 10, 430, 1);
806   }
807   else
808   {
809     if(!Menu::current())
810       white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
811     else
812       white_small_text->draw("No Level Subset loaded", 10, 430, 1);
813   }
814
815 }
816
817 void le_drawlevel()
818 {
819   unsigned int y,x,i,s;
820   Uint8 a;
821
822   /* Draw the real background */
823   if(le_current_level->bkgd_image[0] != '\0')
824   {
825     s = pos_x / 30;
826     le_current_level->img_bkgd->draw_part(s,0,0,0,
827                                           le_current_level->img_bkgd->w - s - 32, le_current_level->img_bkgd->h);
828     le_current_level->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
829                                           le_current_level->img_bkgd->h);
830   }
831   else
832   {
833     drawgradient(le_current_level->bkgd_top, le_current_level->bkgd_bottom);
834   }
835
836   /*       clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
837
838   for (y = 0; y < 15; ++y)
839     for (x = 0; x < 20; ++x)
840     {
841
842       if(active_tm == TM_BG)
843         a = 255;
844       else
845         a = 128;
846
847       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->bg_tiles[y][x + (int)(pos_x / 32)],a);
848
849       if(active_tm == TM_IA)
850         a = 255;
851       else
852         a = 128;
853
854       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)],a);
855
856       if(active_tm == TM_FG)
857         a = 255;
858       else
859         a = 128;
860
861       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->fg_tiles[y][x + (int)(pos_x / 32)],a);
862
863       /* draw whats inside stuff when cursor is selecting those */
864       /* (draw them all the time - is this the right behaviour?) */
865       if(TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images.size() > 0)
866         TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
867
868     }
869
870   /* Draw the Bad guys: */
871   for (i = 0; i < le_world.bad_guys.size(); ++i)
872   {
873     /* to support frames: img_bsod_left[(frame / 5) % 4] */
874
875     scroll_x = pos_x;
876     le_world.bad_guys[i].draw();
877   }
878
879
880   /* Draw the player: */
881   /* for now, the position is fixed at (100, 240) */
882   largetux.walk_right->draw( 100 - pos_x, 240);
883 }
884
885 void le_checkevents()
886 {
887   SDLKey key;
888   SDLMod keymod;
889   Button* pbutton;
890   int x,y;
891
892   keymod = SDL_GetModState();
893
894   while(SDL_PollEvent(&event))
895   {
896     if (Menu::current())
897     {
898       Menu::current()->event(event);
899     }
900     else
901     {
902       mouse_cursor->set_state(MC_NORMAL);
903
904       /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
905       if(event.type == SDL_KEYDOWN
906           || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
907               && (event.motion.x > 0
908                   && event.motion.x < screen->w - 64 &&
909                   event.motion.y > 0 && event.motion.y < screen->h)))
910       {
911         switch(event.type)
912         {
913         case SDL_KEYDOWN:       // key pressed
914           key = event.key.keysym.sym;
915           switch(key)
916           {
917           case SDLK_ESCAPE:
918             Menu::set_current(leveleditor_menu);
919           case SDLK_LEFT:
920             if(fire == DOWN)
921               cursor_x -= KEY_CURSOR_SPEED;
922             else
923               cursor_x -= KEY_CURSOR_FASTSPEED;
924
925             if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
926               pos_x = cursor_x - MOUSE_LEFT_MARGIN;
927
928             break;
929           case SDLK_RIGHT:
930             if(fire == DOWN)
931               cursor_x += KEY_CURSOR_SPEED;
932             else
933               cursor_x += KEY_CURSOR_FASTSPEED;
934
935             if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
936               pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
937
938             break;
939           case SDLK_UP:
940             if(fire == DOWN)
941               cursor_y -= KEY_CURSOR_SPEED;
942             else
943               cursor_y -= KEY_CURSOR_FASTSPEED;
944
945             if(cursor_y < 0)
946               cursor_y = 0;
947             break;
948           case SDLK_DOWN:
949             if(fire == DOWN)
950               cursor_y += KEY_CURSOR_SPEED;
951             else
952               cursor_y += KEY_CURSOR_FASTSPEED;
953
954             if(cursor_y > screen->h-32)
955               cursor_y = screen->h-32;
956             break;
957           case SDLK_LCTRL:
958             fire =UP;
959             break;
960           case SDLK_F1:
961             le_showhelp();
962             break;
963           case SDLK_HOME:
964             cursor_x = 0;
965             pos_x = cursor_x;
966             break;
967           case SDLK_END:
968             cursor_x = (le_current_level->width * 32) - 32;
969             pos_x = cursor_x;
970             break;
971           case SDLK_F9:
972             le_show_grid = !le_show_grid;
973             break;
974           default:
975             break;
976           }
977           break;
978         case SDL_KEYUP: /* key released */
979           switch(event.key.keysym.sym)
980           {
981           case SDLK_LCTRL:
982             fire = DOWN;
983             break;
984           default:
985             break;
986           }
987           break;
988         case SDL_MOUSEBUTTONDOWN:
989           if(event.button.button == SDL_BUTTON_LEFT)
990           {
991             le_mouse_pressed[LEFT] = true;
992
993             selection.x1 = event.motion.x + pos_x;
994             selection.y1 = event.motion.y;
995             selection.x2 = event.motion.x + pos_x;
996             selection.y2 = event.motion.y;
997           }
998           else if(event.button.button == SDL_BUTTON_RIGHT)
999           {
1000             le_mouse_pressed[RIGHT] = true;
1001           }
1002           break;
1003         case SDL_MOUSEBUTTONUP:
1004           if(event.button.button == SDL_BUTTON_LEFT)
1005             le_mouse_pressed[LEFT] = false;
1006           else if(event.button.button == SDL_BUTTON_RIGHT)
1007             le_mouse_pressed[RIGHT] = false;
1008           break;
1009         case SDL_MOUSEMOTION:
1010
1011           if(!Menu::current())
1012           {
1013             x = event.motion.x;
1014             y = event.motion.y;
1015
1016             if(le_current.IsTile())
1017             {
1018             cursor_x = ((int)(pos_x + x) / 32) * 32;
1019             cursor_y = ((int) y / 32) * 32;
1020             }
1021             else
1022             {
1023             cursor_x = x;
1024             cursor_y = y;
1025             }
1026
1027             if(le_mouse_pressed[LEFT])
1028             {
1029               selection.x2 = x + pos_x;
1030               selection.y2 = y;
1031             }
1032
1033             if(le_mouse_pressed[RIGHT])
1034             {
1035               pos_x += -1 * event.motion.xrel;
1036             }
1037           }
1038           break;
1039         case SDL_QUIT:  // window closed
1040           done = 1;
1041           break;
1042         default:
1043           break;
1044         }
1045       }
1046     }
1047
1048     if(le_current_level != NULL)
1049     {
1050       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 &&
1051           event.motion.y > 0 && event.motion.y < screen->h)))
1052       {
1053         le_mouse_pressed[LEFT] = false;
1054         le_mouse_pressed[RIGHT] = false;
1055
1056         if(!Menu::current())
1057         {
1058           /* Check for button events */
1059           le_test_level_bt->event(event);
1060           if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1061             le_testlevel();
1062           le_save_level_bt->event(event);
1063           if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1064             le_current_level->save(le_level_subset->name.c_str(),le_level);
1065           le_exit_bt->event(event);
1066           if(le_exit_bt->get_state() == BUTTON_CLICKED)
1067           {
1068             Menu::set_current(leveleditor_menu);
1069           }
1070           le_next_level_bt->event(event);
1071           if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1072           {
1073             if(le_level < le_level_subset->levels)
1074             {
1075               le_goto_level(++le_level);
1076             }
1077             else
1078             {
1079               Level new_lev;
1080               char str[1024];
1081               sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1082               if(confirm_dialog(str))
1083               {
1084                 new_lev.init_defaults();
1085                 new_lev.save(le_level_subset->name.c_str(),++le_level);
1086                 le_level_subset->levels = le_level;
1087                 le_goto_level(le_level);
1088               }
1089             }
1090           }
1091           le_previous_level_bt->event(event);
1092           if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1093           {
1094             if(le_level > 1)
1095               le_goto_level(--le_level);
1096           }
1097           le_rubber_bt->event(event);
1098           if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1099             le_current.Tile(0);
1100
1101           if(le_selection_mode == SQUARE)
1102           {
1103             le_select_mode_one_bt->event(event);
1104             if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1105               le_selection_mode = CURSOR;
1106           }
1107           else
1108           {
1109             le_select_mode_two_bt->event(event);
1110             if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1111               le_selection_mode = SQUARE;
1112           }
1113
1114           le_tilegroup_bt->event(event);
1115           if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1116           {
1117             Menu::set_current(select_tilegroup_menu);
1118             select_tilegroup_menu_effect.start(200);
1119             select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1120           }
1121
1122           le_objects_bt->event(event);
1123           if(le_objects_bt->get_state() == BUTTON_CLICKED)
1124           {
1125             Menu::set_current(select_objects_menu);
1126             select_objects_menu_effect.start(200);
1127             select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1128           }
1129
1130           le_settings_bt->event(event);
1131           if(le_settings_bt->get_state() == BUTTON_CLICKED)
1132           {
1133             update_level_settings_menu();
1134             Menu::set_current(level_settings_menu);
1135           }
1136           if(!cur_tilegroup.empty())
1137           {
1138             if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1139             {
1140               if(pbutton->get_state() == BUTTON_CLICKED)
1141               {
1142                 le_current.Tile(pbutton->get_tag());
1143               }
1144             }
1145           }
1146           else if(!cur_objects.empty())
1147           {
1148             if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1149             {
1150               if(pbutton->get_state() == BUTTON_CLICKED)
1151               {
1152                 le_current.Object(pbutton->get_game_object());
1153               }
1154             }
1155           }
1156
1157           if((pbutton = le_tilemap_panel->event(event)) != NULL)
1158           {
1159             if(pbutton->get_state() == BUTTON_CLICKED)
1160             {
1161               active_tm = static_cast<TileMapType>(pbutton->get_tag());
1162             }
1163           }
1164         }
1165         else
1166         {
1167           le_settings_bt->event(event);
1168           if(le_settings_bt->get_state() == BUTTON_CLICKED)
1169           {
1170             Menu::set_current(0);
1171           }
1172           le_tilegroup_bt->event(event);
1173           if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1174           {
1175             Menu::set_current(0);
1176           }
1177         }
1178       }
1179
1180       if(!Menu::current())
1181       {
1182         le_move_left_bt->event(event);
1183         le_move_right_bt->event(event);
1184
1185         if(le_mouse_pressed[LEFT])
1186         {
1187           if(le_current.IsTile())
1188             le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1189           else if(le_current.IsObject())
1190           {
1191             std::string type = le_current.obj->type();
1192             if(type == "BadGuy")
1193             {
1194               BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1195               
1196               le_world.bad_guys.push_back(BadGuy(cursor_x, cursor_y,pbadguy->kind,false));
1197               le_current_level->badguy_data.push_back(&le_world.bad_guys.back());
1198             }
1199           }
1200         }
1201       }
1202     }
1203   }
1204   if(!Menu::current())
1205   {
1206     if(le_move_left_bt->get_state() == BUTTON_PRESSED)
1207     {
1208       pos_x -= 192;
1209     }
1210     else if(le_move_left_bt->get_state() == BUTTON_HOVER)
1211     {
1212       pos_x -= 64;
1213     }
1214
1215     if(le_move_right_bt->get_state() == BUTTON_PRESSED)
1216     {
1217       pos_x += 192;
1218     }
1219     else if(le_move_right_bt->get_state() == BUTTON_HOVER)
1220     {
1221       pos_x += 64;
1222     }
1223   }
1224
1225 }
1226
1227 void le_highlight_selection()
1228 {
1229   int x1, x2, y1, y2;
1230
1231   if(selection.x1 < selection.x2)
1232   {
1233     x1 = selection.x1;
1234     x2 = selection.x2;
1235   }
1236   else
1237   {
1238     x1 = selection.x2;
1239     x2 = selection.x1;
1240   }
1241   if(selection.y1 < selection.y2)
1242   {
1243     y1 = selection.y1;
1244     y2 = selection.y2;
1245   }
1246   else
1247   {
1248     y1 = selection.y2;
1249     y2 = selection.y1;
1250   }
1251
1252   x1 /= 32;
1253   x2 /= 32;
1254   y1 /= 32;
1255   y2 /= 32;
1256
1257   fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1258 }
1259
1260 void le_change(float x, float y, int tm, unsigned int c)
1261 {
1262   if(le_current_level != NULL)
1263   {
1264     int xx,yy;
1265     int x1, x2, y1, y2;
1266     unsigned int i;
1267
1268     /*  level_changed = true; */
1269
1270     switch(le_selection_mode)
1271     {
1272     case CURSOR:
1273       le_current_level->change(x,y,tm,c);
1274
1275       base_type cursor_base;
1276       cursor_base.x = x;
1277       cursor_base.y = y;
1278       cursor_base.width = 32;
1279       cursor_base.height = 32;
1280
1281       /* if there is a bad guy over there, remove it */
1282       for(i = 0; i < le_world.bad_guys.size(); ++i)
1283         if(rectcollision(cursor_base,le_world.bad_guys[i].base))
1284         {
1285           le_world.bad_guys.erase(le_world.bad_guys.begin() + i);
1286           le_current_level->badguy_data.erase(le_current_level->badguy_data.begin() + i);
1287           }
1288
1289       break;
1290     case SQUARE:
1291       if(selection.x1 < selection.x2)
1292       {
1293         x1 = selection.x1;
1294         x2 = selection.x2;
1295       }
1296       else
1297       {
1298         x1 = selection.x2;
1299         x2 = selection.x1;
1300       }
1301       if(selection.y1 < selection.y2)
1302       {
1303         y1 = selection.y1;
1304         y2 = selection.y2;
1305       }
1306       else
1307       {
1308         y1 = selection.y2;
1309         y2 = selection.y1;
1310       }
1311
1312       x1 /= 32;
1313       x2 /= 32;
1314       y1 /= 32;
1315       y2 /= 32;
1316
1317       /* if there is a bad guy over there, remove it */
1318       for(std::vector<BadGuy>::iterator i = le_world.bad_guys.begin();
1319           i != le_world.bad_guys.end(); /* will be at end of loop */)
1320       {
1321         if(i->base.x/32 >= x1 && i->base.x/32 <= x2
1322             && i->base.y/32 >= y1 && i->base.y/32 <= y2)
1323         {
1324           i = le_world.bad_guys.erase(i);
1325           continue;
1326         }
1327         else
1328         {
1329           ++i;
1330         }
1331       }
1332
1333       for(xx = x1; xx <= x2; xx++)
1334         for(yy = y1; yy <= y2; yy++)
1335         {
1336           le_current_level->change(xx*32, yy*32, tm, c);
1337
1338         }
1339       break;
1340     default:
1341       break;
1342     }
1343   }
1344 }
1345
1346 void le_testlevel()
1347 {
1348   le_current_level->save("test", le_level);
1349
1350   GameSession session("test",le_level, ST_GL_TEST);
1351   session.run();
1352   player_status.reset();
1353
1354   music_manager->halt_music();
1355
1356   Menu::set_current(leveleditor_menu);
1357   le_world.arrays_free();
1358   le_current_level->load_gfx();
1359   le_world.activate_bad_guys();
1360 }
1361
1362 void le_showhelp()
1363 {
1364   SDL_Event event;
1365   unsigned int i, done_;
1366   char *text[] = {
1367                    "  - This is SuperTux's built-in level editor -",
1368                    "It has been designed to be light and easy to use from the start.",
1369                    "",
1370                    "When you first load the level editor you are given a menu where you",
1371                    "can load level subsets, create a new level subset, edit the current",
1372                    "subset's settings, or simply quit the editor. You can access this menu",
1373                    "from the level editor at any time by pressing the escape key.",
1374                    "",
1375                    "To your right is your button bar. The center of this contains many",
1376                    "tiles you can use to make your level. To select a tile, click on it",
1377                    "with your left mouse button; your selection will be shown in the",
1378                    "bottom right corner of the button box. Click anywhere on your level",
1379                    "with the left mouse button to place that tile down. If you right click",
1380                    "a tile in the button bar, you can find out what its keyboard shortcut",
1381                    "is. The three buttons FGD, BGD and EMY let you pick from foreground,",
1382                    "background, and enemy tiles. The eraser lets you remove tiles.",
1383                    "The left and right arrow keys scroll back and forth through your level.",
1384                    "The button with the wrench and screwdriver, lets you change the",
1385                    "settings of your level, including how long it is or what music it will",
1386                    "play. When you are ready to give your level a test, click on the little",
1387                    "running Tux. If you like the changes you have made to your level,",
1388                    "press the red save key to keep them.",
1389                    "To change which level in your subset you are editing, press the white",
1390                    "up and down arrow keys at the top of the button box.",
1391                    "",
1392                    "Have fun making levels! If you make some good ones, send them to us on",
1393                    "the SuperTux mailing list!",
1394                    "- SuperTux team"
1395                  };
1396
1397
1398   blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1399
1400   for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1401     white_small_text->draw(text[i], 5, 80+(i*white_small_text->h), 1);
1402
1403   gold_text->drawf("Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
1404
1405   flipscreen();
1406
1407   done_ = 0;
1408
1409   while(done_ == 0)
1410   {
1411     done_ = wait_for_event(event);
1412     SDL_Delay(50);
1413   }
1414 }