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