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