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