314a5f09c609f593348229721692bf59e1d9e309
[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       if(!TileManager::instance()->get(*sit)->filenames.empty())
502       {
503         imagefile += TileManager::instance()->get(*sit)->filenames[0];
504       }
505       else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
506       {
507         imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
508       }
509       else
510       {
511         imagefile += "notile.png";
512       }
513       Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
514                                   0, 0, 32, 32);
515       tilegroups_map[it->name]->additem(button, *sit);
516     }
517   }
518   select_tilegroup_menu->additem(MN_HL,"",0,0);
519
520   select_objects_menu->arrange_left = true;
521   select_objects_menu->additem(MN_LABEL,"Select Objects",0,0);
522   select_objects_menu->additem(MN_HL,"",0,0);
523   select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
524   objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
525
526   for(int i = 0; i < NUM_BadGuyKinds; ++i)
527   {
528     BadGuy bad_tmp(0,0,BadGuyKind(i),false);
529     objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
530     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));
531   }
532
533   select_objects_menu->additem(MN_HL,"",0,0);
534
535 }
536
537 int le_init()
538 {
539   level_subsets = dsubdirs("/levels", "info");
540
541   le_level_subset = new LevelSubset;
542
543   active_tm = TM_IA;
544
545   le_show_grid = true;
546
547   /*  level_changed = NO;*/
548   fire = DOWN;
549   done = 0;
550   le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
551   le_level_changed = false;
552   le_current_level = NULL;
553
554   le_mouse_pressed[LEFT] = false;
555   le_mouse_pressed[RIGHT] = false;
556
557   le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
558
559   select_tilegroup_menu_effect.init(false);
560   select_objects_menu_effect.init(false);
561
562   /* Load buttons */
563   le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
564   le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F6,screen->w-32,32);
565   le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
566   le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
567   le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
568   le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
569   le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
570   le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
571   le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
572   le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
573   le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
574   le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
575   le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F7,screen->w-64,80);
576
577   le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
578   le_tilemap_panel->set_button_size(32,10);
579   le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_F4,0,0),TM_BG);
580   le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_F4,0,0),TM_IA);
581   le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_F4,0,0),TM_FG);
582
583   le_init_menus();
584
585   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
586
587   return 0;
588 }
589
590 void update_level_settings_menu()
591 {
592   char str[80];
593   int i;
594
595   level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_current_level->name.c_str());
596   level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_current_level->author.c_str());
597
598   string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
599   string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
600   string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
601
602   if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_current_level->song_title.c_str())) != -1)
603     level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
604   if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_current_level->bkgd_image.c_str())) != -1)
605     level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
606
607   sprintf(str,"%d",le_current_level->width);
608   level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
609   sprintf(str,"%d",le_current_level->time_left);
610   level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
611   sprintf(str,"%2.0f",le_current_level->gravity);
612   level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
613   sprintf(str,"%d",le_current_level->bkgd_top.red);
614   level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
615   sprintf(str,"%d",le_current_level->bkgd_top.green);
616   level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
617   sprintf(str,"%d",le_current_level->bkgd_top.blue);
618   level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
619   sprintf(str,"%d",le_current_level->bkgd_bottom.red);
620   level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
621   sprintf(str,"%d",le_current_level->bkgd_bottom.green);
622   level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
623   sprintf(str,"%d",le_current_level->bkgd_bottom.blue);
624   level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
625 }
626
627 void update_subset_settings_menu()
628 {
629   subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
630   subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
631 }
632
633 void apply_level_settings_menu()
634 {
635   int i;
636   i = false;
637
638   le_current_level->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
639   le_current_level->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
640
641   if(le_current_level->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
642   {
643     le_current_level->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
644     i = true;
645   }
646
647   if(i)
648   {
649     le_current_level->load_gfx();
650   }
651
652   le_current_level->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
653
654   le_current_level->change_size(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
655   le_current_level->time_left = atoi(level_settings_menu->get_item_by_id(MNID_BGIMG).input);
656   le_current_level->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
657   le_current_level->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
658   le_current_level->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
659   le_current_level->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
660   le_current_level->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
661   le_current_level->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
662   le_current_level->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
663 }
664
665 void save_subset_settings_menu()
666 {
667   le_level_subset->title = subset_settings_menu->item[2].input;
668   le_level_subset->description = subset_settings_menu->item[3].input;
669   le_level_subset->save();
670 }
671
672 void le_goto_level(int levelnb)
673 {
674   le_world.arrays_free();
675
676   le_current_level->cleanup();
677   if(le_current_level->load(le_level_subset->name.c_str(), levelnb) != 0)
678   {
679     le_current_level->load(le_level_subset->name.c_str(), le_level);
680   }
681   else
682   {
683     le_level = levelnb;
684   }
685
686   le_set_defaults();
687
688   le_current_level->load_gfx();
689
690   le_world.activate_bad_guys();
691 }
692
693 void le_quit(void)
694 {
695   /*if(level_changed == true)
696     if(askforsaving() == CANCEL)
697       return;*/ //FIXME
698
699   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
700
701   delete le_selection;
702   delete leveleditor_menu;
703   delete subset_load_menu;
704   delete subset_new_menu;
705   delete subset_settings_menu;
706   delete level_settings_menu;
707   delete select_tilegroup_menu;
708   delete select_objects_menu;
709   delete le_save_level_bt;
710   delete le_exit_bt;
711   delete le_test_level_bt;
712   delete le_next_level_bt;
713   delete le_previous_level_bt;
714   delete le_move_right_bt;
715   delete le_move_left_bt;
716   delete le_rubber_bt;
717   delete le_select_mode_one_bt;
718   delete le_select_mode_two_bt;
719   delete le_settings_bt;
720   delete le_tilegroup_bt;
721   delete le_objects_bt;
722   delete le_tilemap_panel;
723
724   delete le_current_level;
725   le_current_level = 0;
726   delete le_level_subset;
727   le_level_subset = 0;
728
729   for(ButtonPanelMap::iterator i = tilegroups_map.begin();
730       i != tilegroups_map.end(); ++i)
731   {
732     delete i->second;
733   }
734   for(ButtonPanelMap::iterator i = objects_map.begin();
735       i != objects_map.end(); ++i)
736   {
737     delete i->second;
738   }
739 }
740
741 void le_drawinterface()
742 {
743   int x,y;
744   char str[80];
745
746   if(le_current_level != NULL)
747   {
748     /* draw a grid (if selected) */
749     if(le_show_grid)
750     {
751       for(x = 0; x < 19; x++)
752         fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
753       for(y = 0; y < 15; y++)
754         fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
755     }
756   }
757
758   if(le_selection_mode == CURSOR)
759     le_selection->draw( cursor_x - pos_x, cursor_y);
760   else if(le_selection_mode == SQUARE)
761   {
762     int w, h;
763     le_highlight_selection();
764     /* draw current selection */
765     w = selection.x2 - selection.x1;
766     h = selection.y2 - selection.y1;
767     fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
768     fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
769     fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
770     fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
771   }
772
773
774   /* draw button bar */
775   fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
776
777   if(le_current.IsTile())
778   {
779     Tile::draw(19 * 32, 14 * 32, le_current.tile);
780     if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
781       TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
782   }
783
784   //if(le_current.IsObject())
785   //printf("");
786
787   if(le_current_level != NULL)
788   {
789     le_save_level_bt->draw();
790     le_exit_bt->draw();
791     le_test_level_bt->draw();
792     le_next_level_bt->draw();
793     le_previous_level_bt->draw();
794     le_rubber_bt->draw();
795     if(le_selection_mode == SQUARE)
796       le_select_mode_one_bt->draw();
797     else if(le_selection_mode == CURSOR)
798       le_select_mode_two_bt->draw();
799     le_settings_bt->draw();
800     le_move_right_bt->draw();
801     le_move_left_bt->draw();
802     le_tilegroup_bt->draw();
803     le_objects_bt->draw();
804     if(!cur_tilegroup.empty())
805       tilegroups_map[cur_tilegroup]->draw();
806     else if(!cur_objects.empty())
807     {
808       objects_map[cur_objects]->draw();
809     }
810
811     le_tilemap_panel->draw();
812
813     sprintf(str, "%d/%d", le_level,le_level_subset->levels);
814     white_text->drawf(str, -10, 16, A_RIGHT, A_TOP, 0);
815
816     white_small_text->draw("F1 for Help", 10, 430, 1);
817   }
818   else
819   {
820     if(!Menu::current())
821       white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
822     else
823       white_small_text->draw("No Level Subset loaded", 10, 430, 1);
824   }
825
826 }
827
828 void le_drawlevel()
829 {
830   unsigned int y,x,i,s;
831   Uint8 a;
832
833   /* Draw the real background */
834   if(le_current_level->bkgd_image[0] != '\0')
835   {
836     s = pos_x / 30;
837     le_current_level->img_bkgd->draw_part(s,0,0,0,
838                                           le_current_level->img_bkgd->w - s - 32, le_current_level->img_bkgd->h);
839     le_current_level->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
840                                           le_current_level->img_bkgd->h);
841   }
842   else
843   {
844     drawgradient(le_current_level->bkgd_top, le_current_level->bkgd_bottom);
845   }
846
847   /*       clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
848
849   for (y = 0; y < 15; ++y)
850     for (x = 0; x < 20; ++x)
851     {
852
853       if(active_tm == TM_BG)
854         a = 255;
855       else
856         a = 128;
857
858       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->bg_tiles[y][x + (int)(pos_x / 32)],a);
859
860       if(active_tm == TM_IA)
861         a = 255;
862       else
863         a = 128;
864
865       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)],a);
866
867       if(active_tm == TM_FG)
868         a = 255;
869       else
870         a = 128;
871
872       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->fg_tiles[y][x + (int)(pos_x / 32)],a);
873
874       /* draw whats inside stuff when cursor is selecting those */
875       /* (draw them all the time - is this the right behaviour?) */
876       if(TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images.size() > 0)
877         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);
878
879     }
880
881   /* Draw the Bad guys: */
882   for (i = 0; i < le_world.bad_guys.size(); ++i)
883   {
884     /* to support frames: img_bsod_left[(frame / 5) % 4] */
885
886     scroll_x = pos_x;
887     le_world.bad_guys[i].draw();
888   }
889
890
891   /* Draw the player: */
892   /* for now, the position is fixed at (100, 240) */
893   largetux.walk_right->draw( 100 - pos_x, 240);
894 }
895
896 void le_checkevents()
897 {
898   SDLKey key;
899   SDLMod keymod;
900   Button* pbutton;
901   int x,y;
902
903   keymod = SDL_GetModState();
904
905   while(SDL_PollEvent(&event))
906   {
907     if (Menu::current())
908     {
909       Menu::current()->event(event);
910     }
911     else
912     {
913       mouse_cursor->set_state(MC_NORMAL);
914
915       /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
916       if(event.type == SDL_KEYDOWN
917           || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
918               && (event.motion.x > 0
919                   && event.motion.x < screen->w - 64 &&
920                   event.motion.y > 0 && event.motion.y < screen->h)))
921       {
922         switch(event.type)
923         {
924         case SDL_KEYDOWN:       // key pressed
925           key = event.key.keysym.sym;
926           switch(key)
927           {
928           case SDLK_ESCAPE:
929             Menu::set_current(leveleditor_menu);
930           case SDLK_LEFT:
931             if(fire == DOWN)
932               cursor_x -= KEY_CURSOR_SPEED;
933             else
934               cursor_x -= KEY_CURSOR_FASTSPEED;
935
936             if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
937               pos_x = cursor_x - MOUSE_LEFT_MARGIN;
938
939             break;
940           case SDLK_RIGHT:
941             if(fire == DOWN)
942               cursor_x += KEY_CURSOR_SPEED;
943             else
944               cursor_x += KEY_CURSOR_FASTSPEED;
945
946             if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
947               pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
948
949             break;
950           case SDLK_UP:
951             if(fire == DOWN)
952               cursor_y -= KEY_CURSOR_SPEED;
953             else
954               cursor_y -= KEY_CURSOR_FASTSPEED;
955
956             if(cursor_y < 0)
957               cursor_y = 0;
958             break;
959           case SDLK_DOWN:
960             if(fire == DOWN)
961               cursor_y += KEY_CURSOR_SPEED;
962             else
963               cursor_y += KEY_CURSOR_FASTSPEED;
964
965             if(cursor_y > screen->h-32)
966               cursor_y = screen->h-32;
967             break;
968           case SDLK_LCTRL:
969             fire =UP;
970             break;
971           case SDLK_F1:
972             le_showhelp();
973             break;
974           case SDLK_HOME:
975             cursor_x = 0;
976             pos_x = cursor_x;
977             break;
978           case SDLK_END:
979             cursor_x = (le_current_level->width * 32) - 32;
980             pos_x = cursor_x;
981             break;
982           case SDLK_F9:
983             le_show_grid = !le_show_grid;
984             break;
985           default:
986             break;
987           }
988           break;
989         case SDL_KEYUP: /* key released */
990           switch(event.key.keysym.sym)
991           {
992           case SDLK_LCTRL:
993             fire = DOWN;
994             break;
995           default:
996             break;
997           }
998           break;
999         case SDL_MOUSEBUTTONDOWN:
1000           if(event.button.button == SDL_BUTTON_LEFT)
1001           {
1002             le_mouse_pressed[LEFT] = true;
1003
1004             selection.x1 = event.motion.x + pos_x;
1005             selection.y1 = event.motion.y;
1006             selection.x2 = event.motion.x + pos_x;
1007             selection.y2 = event.motion.y;
1008           }
1009           else if(event.button.button == SDL_BUTTON_RIGHT)
1010           {
1011             le_mouse_pressed[RIGHT] = true;
1012           }
1013           break;
1014         case SDL_MOUSEBUTTONUP:
1015           if(event.button.button == SDL_BUTTON_LEFT)
1016             le_mouse_pressed[LEFT] = false;
1017           else if(event.button.button == SDL_BUTTON_RIGHT)
1018             le_mouse_pressed[RIGHT] = false;
1019           break;
1020         case SDL_MOUSEMOTION:
1021
1022           if(!Menu::current())
1023           {
1024             x = event.motion.x;
1025             y = event.motion.y;
1026
1027             if(le_current.IsTile())
1028             {
1029               cursor_x = ((int)(pos_x + x) / 32) * 32;
1030               cursor_y = ((int) y / 32) * 32;
1031             }
1032             else
1033             {
1034               cursor_x = x;
1035               cursor_y = y;
1036             }
1037
1038             if(le_mouse_pressed[LEFT])
1039             {
1040               selection.x2 = x + pos_x;
1041               selection.y2 = y;
1042             }
1043
1044             if(le_mouse_pressed[RIGHT])
1045             {
1046               pos_x += -1 * event.motion.xrel;
1047             }
1048           }
1049           break;
1050         case SDL_QUIT:  // window closed
1051           done = 1;
1052           break;
1053         default:
1054           break;
1055         }
1056       }
1057     }
1058
1059     if(le_current_level != NULL)
1060     {
1061       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 &&
1062           event.motion.y > 0 && event.motion.y < screen->h)))
1063       {
1064         le_mouse_pressed[LEFT] = false;
1065         le_mouse_pressed[RIGHT] = false;
1066
1067         if(!Menu::current())
1068         {
1069           /* Check for button events */
1070           le_test_level_bt->event(event);
1071           if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1072             le_testlevel();
1073           le_save_level_bt->event(event);
1074           if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1075             le_current_level->save(le_level_subset->name.c_str(),le_level);
1076           le_exit_bt->event(event);
1077           if(le_exit_bt->get_state() == BUTTON_CLICKED)
1078           {
1079             Menu::set_current(leveleditor_menu);
1080           }
1081           le_next_level_bt->event(event);
1082           if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1083           {
1084             if(le_level < le_level_subset->levels)
1085             {
1086               le_goto_level(++le_level);
1087             }
1088             else
1089             {
1090               Level new_lev;
1091               char str[1024];
1092               sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1093               if(confirm_dialog(str))
1094               {
1095                 new_lev.init_defaults();
1096                 new_lev.save(le_level_subset->name.c_str(),++le_level);
1097                 le_level_subset->levels = le_level;
1098                 le_goto_level(le_level);
1099               }
1100             }
1101           }
1102           le_previous_level_bt->event(event);
1103           if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1104           {
1105             if(le_level > 1)
1106               le_goto_level(--le_level);
1107           }
1108           le_rubber_bt->event(event);
1109           if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1110             le_current.Tile(0);
1111
1112           if(le_selection_mode == SQUARE)
1113           {
1114             le_select_mode_one_bt->event(event);
1115             if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1116               le_selection_mode = CURSOR;
1117           }
1118           else
1119           {
1120             le_select_mode_two_bt->event(event);
1121             if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1122               le_selection_mode = SQUARE;
1123           }
1124
1125           le_tilegroup_bt->event(event);
1126           if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1127           {
1128             Menu::set_current(select_tilegroup_menu);
1129             select_tilegroup_menu_effect.start(200);
1130             select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1131           }
1132
1133           le_objects_bt->event(event);
1134           if(le_objects_bt->get_state() == BUTTON_CLICKED)
1135           {
1136             Menu::set_current(select_objects_menu);
1137             select_objects_menu_effect.start(200);
1138             select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1139           }
1140
1141           le_settings_bt->event(event);
1142           if(le_settings_bt->get_state() == BUTTON_CLICKED)
1143           {
1144             update_level_settings_menu();
1145             Menu::set_current(level_settings_menu);
1146           }
1147           if(!cur_tilegroup.empty())
1148           {
1149             if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1150             {
1151               if(pbutton->get_state() == BUTTON_CLICKED)
1152               {
1153                 le_current.Tile(pbutton->get_tag());
1154               }
1155             }
1156           }
1157           else if(!cur_objects.empty())
1158           {
1159             if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1160             {
1161               if(pbutton->get_state() == BUTTON_CLICKED)
1162               {
1163                 le_current.Object(pbutton->get_game_object());
1164               }
1165             }
1166           }
1167
1168           if((pbutton = le_tilemap_panel->event(event)) != NULL)
1169           {
1170             if(pbutton->get_state() == BUTTON_CLICKED)
1171             {
1172               active_tm = static_cast<TileMapType>(pbutton->get_tag());
1173             }
1174           }
1175         }
1176         else
1177         {
1178           le_settings_bt->event(event);
1179           if(le_settings_bt->get_state() == BUTTON_CLICKED)
1180           {
1181             Menu::set_current(0);
1182           }
1183           le_tilegroup_bt->event(event);
1184           if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1185           {
1186             Menu::set_current(0);
1187           }
1188         }
1189       }
1190
1191       if(!Menu::current())
1192       {
1193         le_move_left_bt->event(event);
1194         le_move_right_bt->event(event);
1195
1196         if(le_mouse_pressed[LEFT])
1197         {
1198           if(le_current.IsTile())
1199             le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1200           else if(le_current.IsObject())
1201           {
1202             std::string type = le_current.obj->type();
1203             if(type == "BadGuy")
1204             {
1205               BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1206
1207               le_world.bad_guys.push_back(BadGuy(cursor_x, cursor_y,pbadguy->kind,false));
1208               le_current_level->badguy_data.push_back(&le_world.bad_guys.back());
1209             }
1210           }
1211         }
1212       }
1213     }
1214   }
1215   if(!Menu::current())
1216   {
1217     if(le_move_left_bt->get_state() == BUTTON_PRESSED)
1218     {
1219       pos_x -= 192;
1220     }
1221     else if(le_move_left_bt->get_state() == BUTTON_HOVER)
1222     {
1223       pos_x -= 64;
1224     }
1225
1226     if(le_move_right_bt->get_state() == BUTTON_PRESSED)
1227     {
1228       pos_x += 192;
1229     }
1230     else if(le_move_right_bt->get_state() == BUTTON_HOVER)
1231     {
1232       pos_x += 64;
1233     }
1234   }
1235
1236 }
1237
1238 void le_highlight_selection()
1239 {
1240   int x1, x2, y1, y2;
1241
1242   if(selection.x1 < selection.x2)
1243   {
1244     x1 = selection.x1;
1245     x2 = selection.x2;
1246   }
1247   else
1248   {
1249     x1 = selection.x2;
1250     x2 = selection.x1;
1251   }
1252   if(selection.y1 < selection.y2)
1253   {
1254     y1 = selection.y1;
1255     y2 = selection.y2;
1256   }
1257   else
1258   {
1259     y1 = selection.y2;
1260     y2 = selection.y1;
1261   }
1262
1263   x1 /= 32;
1264   x2 /= 32;
1265   y1 /= 32;
1266   y2 /= 32;
1267
1268   fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1269 }
1270
1271 void le_change(float x, float y, int tm, unsigned int c)
1272 {
1273   if(le_current_level != NULL)
1274   {
1275     int xx,yy;
1276     int x1, x2, y1, y2;
1277     unsigned int i;
1278
1279     /*  level_changed = true; */
1280
1281     switch(le_selection_mode)
1282     {
1283     case CURSOR:
1284       le_current_level->change(x,y,tm,c);
1285
1286       base_type cursor_base;
1287       cursor_base.x = x;
1288       cursor_base.y = y;
1289       cursor_base.width = 32;
1290       cursor_base.height = 32;
1291
1292       /* if there is a bad guy over there, remove it */
1293       for(i = 0; i < le_world.bad_guys.size(); ++i)
1294         if(rectcollision(cursor_base,le_world.bad_guys[i].base))
1295         {
1296           le_world.bad_guys.erase(le_world.bad_guys.begin() + i);
1297           le_current_level->badguy_data.erase(le_current_level->badguy_data.begin() + i);
1298         }
1299
1300       break;
1301     case SQUARE:
1302       if(selection.x1 < selection.x2)
1303       {
1304         x1 = selection.x1;
1305         x2 = selection.x2;
1306       }
1307       else
1308       {
1309         x1 = selection.x2;
1310         x2 = selection.x1;
1311       }
1312       if(selection.y1 < selection.y2)
1313       {
1314         y1 = selection.y1;
1315         y2 = selection.y2;
1316       }
1317       else
1318       {
1319         y1 = selection.y2;
1320         y2 = selection.y1;
1321       }
1322
1323       x1 /= 32;
1324       x2 /= 32;
1325       y1 /= 32;
1326       y2 /= 32;
1327
1328       /* if there is a bad guy over there, remove it */
1329       for(std::vector<BadGuy>::iterator i = le_world.bad_guys.begin();
1330           i != le_world.bad_guys.end(); /* will be at end of loop */)
1331       {
1332         if(i->base.x/32 >= x1 && i->base.x/32 <= x2
1333             && i->base.y/32 >= y1 && i->base.y/32 <= y2)
1334         {
1335           i = le_world.bad_guys.erase(i);
1336           continue;
1337         }
1338         else
1339         {
1340           ++i;
1341         }
1342       }
1343
1344       for(xx = x1; xx <= x2; xx++)
1345         for(yy = y1; yy <= y2; yy++)
1346         {
1347           le_current_level->change(xx*32, yy*32, tm, c);
1348
1349         }
1350       break;
1351     default:
1352       break;
1353     }
1354   }
1355 }
1356
1357 void le_testlevel()
1358 {
1359   le_current_level->save("test", le_level);
1360
1361   GameSession session("test",le_level, ST_GL_TEST);
1362   session.run();
1363   player_status.reset();
1364
1365   music_manager->halt_music();
1366
1367   Menu::set_current(leveleditor_menu);
1368   le_world.arrays_free();
1369   le_current_level->load_gfx();
1370   le_world.activate_bad_guys();
1371 }
1372
1373 void le_showhelp()
1374 {
1375   SDL_Event event;
1376   unsigned int i, done_;
1377   char *text[] = {
1378                    "  - This is SuperTux's built-in level editor -",
1379                    "It has been designed to be light and easy to use from the start.",
1380                    "",
1381                    "When you first load the level editor you are given a menu where you",
1382                    "can load level subsets, create a new level subset, edit the current",
1383                    "subset's settings, or simply quit the editor. You can access this menu",
1384                    "from the level editor at any time by pressing the escape key.",
1385                    "",
1386                    "To your right is your button bar. The center of this contains many",
1387                    "tiles you can use to make your level. To select a tile, click on it",
1388                    "with your left mouse button; your selection will be shown in the",
1389                    "bottom right corner of the button box. Click anywhere on your level",
1390                    "with the left mouse button to place that tile down. If you right click",
1391                    "a tile in the button bar, you can find out what its keyboard shortcut",
1392                    "is. The three buttons FGD, BGD and EMY let you pick from foreground,",
1393                    "background, and enemy tiles. The eraser lets you remove tiles.",
1394                    "The left and right arrow keys scroll back and forth through your level.",
1395                    "The button with the wrench and screwdriver, lets you change the",
1396                    "settings of your level, including how long it is or what music it will",
1397                    "play. When you are ready to give your level a test, click on the little",
1398                    "running Tux. If you like the changes you have made to your level,",
1399                    "press the red save key to keep them.",
1400                    "To change which level in your subset you are editing, press the white",
1401                    "up and down arrow keys at the top of the button box.",
1402                    "",
1403                    "Have fun making levels! If you make some good ones, send them to us on",
1404                    "the SuperTux mailing list!",
1405                    "- SuperTux team"
1406                  };
1407
1408
1409   blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1410
1411   for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1412     white_small_text->draw(text[i], 5, 80+(i*white_small_text->h), 1);
1413
1414   gold_text->drawf("Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
1415
1416   flipscreen();
1417
1418   done_ = 0;
1419
1420   while(done_ == 0)
1421   {
1422     done_ = wait_for_event(event);
1423     SDL_Delay(50);
1424   }
1425 }