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