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