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