added files for windows installer
[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   
788   //if(le_current.IsObject())
789   //printf("");
790
791   if(le_current_level != NULL)
792   {
793     le_save_level_bt->draw();
794     le_exit_bt->draw();
795     le_test_level_bt->draw();
796     le_next_level_bt->draw();
797     le_previous_level_bt->draw();
798     le_rubber_bt->draw();
799     if(le_selection_mode == SQUARE)
800       le_select_mode_one_bt->draw();
801     else if(le_selection_mode == CURSOR)
802       le_select_mode_two_bt->draw();
803     le_settings_bt->draw();
804     le_move_right_bt->draw();
805     le_move_left_bt->draw();
806     le_tilegroup_bt->draw();
807     le_objects_bt->draw();
808     if(!cur_tilegroup.empty())
809       tilegroups_map[cur_tilegroup]->draw();
810     else if(!cur_objects.empty())
811     {
812       objects_map[cur_objects]->draw();
813     }
814
815     le_tilemap_panel->draw();
816
817     sprintf(str, "%d/%d", le_level,le_level_subset->levels);
818     white_text->drawf(str, -10, 16, A_RIGHT, A_TOP, 0);
819
820     white_small_text->draw("F1 for Help", 10, 430, 1);
821   }
822   else
823   {
824     if(!Menu::current())
825       white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
826     else
827       white_small_text->draw("No Level Subset loaded", 10, 430, 1);
828   }
829
830 }
831
832 void le_drawlevel()
833 {
834   unsigned int y,x,i,s;
835   Uint8 a;
836
837   /* Draw the real background */
838   if(le_current_level->bkgd_image[0] != '\0')
839   {
840     s = pos_x / 30;
841     le_current_level->img_bkgd->draw_part(s,0,0,0,
842                                           le_current_level->img_bkgd->w - s - 32, le_current_level->img_bkgd->h);
843     le_current_level->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
844                                           le_current_level->img_bkgd->h);
845   }
846   else
847   {
848     drawgradient(le_current_level->bkgd_top, le_current_level->bkgd_bottom);
849   }
850
851   /*       clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
852
853   for (y = 0; y < 15; ++y)
854     for (x = 0; x < 20; ++x)
855     {
856
857       if(active_tm == TM_BG)
858         a = 255;
859       else
860         a = 128;
861
862       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->bg_tiles[y][x + (int)(pos_x / 32)],a);
863
864       if(active_tm == TM_IA)
865         a = 255;
866       else
867         a = 128;
868
869       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)],a);
870
871       if(active_tm == TM_FG)
872         a = 255;
873       else
874         a = 128;
875
876       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->fg_tiles[y][x + (int)(pos_x / 32)],a);
877
878       /* draw whats inside stuff when cursor is selecting those */
879       /* (draw them all the time - is this the right behaviour?) */
880       if(TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images.size() > 0)
881         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);
882
883     }
884
885   /* Draw the Bad guys: */
886   for (i = 0; i < le_world.bad_guys.size(); ++i)
887   {
888     /* to support frames: img_bsod_left[(frame / 5) % 4] */
889
890     scroll_x = pos_x;
891     le_world.bad_guys[i].draw();
892   }
893
894
895   /* Draw the player: */
896   /* for now, the position is fixed at (100, 240) */
897   largetux.walk_right->draw( 100 - pos_x, 240);
898 }
899
900 void le_checkevents()
901 {
902   SDLKey key;
903   SDLMod keymod;
904   Button* pbutton;
905   int x,y;
906
907   keymod = SDL_GetModState();
908
909   while(SDL_PollEvent(&event))
910   {
911     if (Menu::current())
912     {
913       Menu::current()->event(event);
914     }
915     else
916     {
917       mouse_cursor->set_state(MC_NORMAL);
918
919       /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
920       if(event.type == SDL_KEYDOWN
921           || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
922               && (event.motion.x > 0
923                   && event.motion.x < screen->w - 64 &&
924                   event.motion.y > 0 && event.motion.y < screen->h)))
925       {
926         switch(event.type)
927         {
928         case SDL_KEYDOWN:       // key pressed
929           key = event.key.keysym.sym;
930           switch(key)
931           {
932           case SDLK_ESCAPE:
933             Menu::set_current(leveleditor_menu);
934           case SDLK_LEFT:
935             if(fire == DOWN)
936               cursor_x -= KEY_CURSOR_SPEED;
937             else
938               cursor_x -= KEY_CURSOR_FASTSPEED;
939
940             if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
941               pos_x = cursor_x - MOUSE_LEFT_MARGIN;
942
943             break;
944           case SDLK_RIGHT:
945             if(fire == DOWN)
946               cursor_x += KEY_CURSOR_SPEED;
947             else
948               cursor_x += KEY_CURSOR_FASTSPEED;
949
950             if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
951               pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
952
953             break;
954           case SDLK_UP:
955             if(fire == DOWN)
956               cursor_y -= KEY_CURSOR_SPEED;
957             else
958               cursor_y -= KEY_CURSOR_FASTSPEED;
959
960             if(cursor_y < 0)
961               cursor_y = 0;
962             break;
963           case SDLK_DOWN:
964             if(fire == DOWN)
965               cursor_y += KEY_CURSOR_SPEED;
966             else
967               cursor_y += KEY_CURSOR_FASTSPEED;
968
969             if(cursor_y > screen->h-32)
970               cursor_y = screen->h-32;
971             break;
972           case SDLK_LCTRL:
973             fire =UP;
974             break;
975           case SDLK_F1:
976             le_showhelp();
977             break;
978           case SDLK_HOME:
979             cursor_x = 0;
980             pos_x = cursor_x;
981             break;
982           case SDLK_END:
983             cursor_x = (le_current_level->width * 32) - 32;
984             pos_x = cursor_x;
985             break;
986           case SDLK_F9:
987             le_show_grid = !le_show_grid;
988             break;
989           default:
990             break;
991           }
992           break;
993         case SDL_KEYUP: /* key released */
994           switch(event.key.keysym.sym)
995           {
996           case SDLK_LCTRL:
997             fire = DOWN;
998             break;
999           default:
1000             break;
1001           }
1002           break;
1003         case SDL_MOUSEBUTTONDOWN:
1004           if(event.button.button == SDL_BUTTON_LEFT)
1005           {
1006             le_mouse_pressed[LEFT] = true;
1007
1008             selection.x1 = event.motion.x + pos_x;
1009             selection.y1 = event.motion.y;
1010             selection.x2 = event.motion.x + pos_x;
1011             selection.y2 = event.motion.y;
1012           }
1013           else if(event.button.button == SDL_BUTTON_RIGHT)
1014           {
1015             le_mouse_pressed[RIGHT] = true;
1016           }
1017           break;
1018         case SDL_MOUSEBUTTONUP:
1019           if(event.button.button == SDL_BUTTON_LEFT)
1020             le_mouse_pressed[LEFT] = false;
1021           else if(event.button.button == SDL_BUTTON_RIGHT)
1022             le_mouse_pressed[RIGHT] = false;
1023           break;
1024         case SDL_MOUSEMOTION:
1025
1026           if(!Menu::current())
1027           {
1028             x = event.motion.x;
1029             y = event.motion.y;
1030
1031             if(le_current.IsTile())
1032             {
1033             cursor_x = ((int)(pos_x + x) / 32) * 32;
1034             cursor_y = ((int) y / 32) * 32;
1035             }
1036             else
1037             {
1038             cursor_x = x;
1039             cursor_y = y;
1040             }
1041
1042             if(le_mouse_pressed[LEFT])
1043             {
1044               selection.x2 = x + pos_x;
1045               selection.y2 = y;
1046             }
1047
1048             if(le_mouse_pressed[RIGHT])
1049             {
1050               pos_x += -1 * event.motion.xrel;
1051             }
1052           }
1053           break;
1054         case SDL_QUIT:  // window closed
1055           done = 1;
1056           break;
1057         default:
1058           break;
1059         }
1060       }
1061     }
1062
1063     if(le_current_level != NULL)
1064     {
1065       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 &&
1066           event.motion.y > 0 && event.motion.y < screen->h)))
1067       {
1068         le_mouse_pressed[LEFT] = false;
1069         le_mouse_pressed[RIGHT] = false;
1070
1071         if(!Menu::current())
1072         {
1073           /* Check for button events */
1074           le_test_level_bt->event(event);
1075           if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1076             le_testlevel();
1077           le_save_level_bt->event(event);
1078           if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1079             le_current_level->save(le_level_subset->name.c_str(),le_level);
1080           le_exit_bt->event(event);
1081           if(le_exit_bt->get_state() == BUTTON_CLICKED)
1082           {
1083             Menu::set_current(leveleditor_menu);
1084           }
1085           le_next_level_bt->event(event);
1086           if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1087           {
1088             if(le_level < le_level_subset->levels)
1089             {
1090               le_goto_level(++le_level);
1091             }
1092             else
1093             {
1094               Level new_lev;
1095               char str[1024];
1096               sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1097               if(confirm_dialog(str))
1098               {
1099                 new_lev.init_defaults();
1100                 new_lev.save(le_level_subset->name.c_str(),++le_level);
1101                 le_level_subset->levels = le_level;
1102                 le_goto_level(le_level);
1103               }
1104             }
1105           }
1106           le_previous_level_bt->event(event);
1107           if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1108           {
1109             if(le_level > 1)
1110               le_goto_level(--le_level);
1111           }
1112           le_rubber_bt->event(event);
1113           if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1114             le_current.Tile(0);
1115
1116           if(le_selection_mode == SQUARE)
1117           {
1118             le_select_mode_one_bt->event(event);
1119             if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1120               le_selection_mode = CURSOR;
1121           }
1122           else
1123           {
1124             le_select_mode_two_bt->event(event);
1125             if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1126               le_selection_mode = SQUARE;
1127           }
1128
1129           le_tilegroup_bt->event(event);
1130           if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1131           {
1132             Menu::set_current(select_tilegroup_menu);
1133             select_tilegroup_menu_effect.start(200);
1134             select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1135           }
1136
1137           le_objects_bt->event(event);
1138           if(le_objects_bt->get_state() == BUTTON_CLICKED)
1139           {
1140             Menu::set_current(select_objects_menu);
1141             select_objects_menu_effect.start(200);
1142             select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1143           }
1144
1145           le_settings_bt->event(event);
1146           if(le_settings_bt->get_state() == BUTTON_CLICKED)
1147           {
1148             update_level_settings_menu();
1149             Menu::set_current(level_settings_menu);
1150           }
1151           if(!cur_tilegroup.empty())
1152           {
1153             if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1154             {
1155               if(pbutton->get_state() == BUTTON_CLICKED)
1156               {
1157                 le_current.Tile(pbutton->get_tag());
1158               }
1159             }
1160           }
1161           else if(!cur_objects.empty())
1162           {
1163             if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1164             {
1165               if(pbutton->get_state() == BUTTON_CLICKED)
1166               {
1167                 le_current.Object(pbutton->get_game_object());
1168               }
1169             }
1170           }
1171
1172           if((pbutton = le_tilemap_panel->event(event)) != NULL)
1173           {
1174             if(pbutton->get_state() == BUTTON_CLICKED)
1175             {
1176               active_tm = static_cast<TileMapType>(pbutton->get_tag());
1177             }
1178           }
1179         }
1180         else
1181         {
1182           le_settings_bt->event(event);
1183           if(le_settings_bt->get_state() == BUTTON_CLICKED)
1184           {
1185             Menu::set_current(0);
1186           }
1187           le_tilegroup_bt->event(event);
1188           if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1189           {
1190             Menu::set_current(0);
1191           }
1192         }
1193       }
1194
1195       if(!Menu::current())
1196       {
1197         le_move_left_bt->event(event);
1198         le_move_right_bt->event(event);
1199
1200         if(le_mouse_pressed[LEFT])
1201         {
1202           if(le_current.IsTile())
1203             le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1204           else if(le_current.IsObject())
1205           {
1206             std::string type = le_current.obj->type();
1207             if(type == "BadGuy")
1208             {
1209               BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1210               
1211               le_world.bad_guys.push_back(BadGuy(cursor_x, cursor_y,pbadguy->kind,false));
1212               le_current_level->badguy_data.push_back(&le_world.bad_guys.back());
1213             }
1214           }
1215         }
1216       }
1217     }
1218   }
1219   if(!Menu::current())
1220   {
1221     if(le_move_left_bt->get_state() == BUTTON_PRESSED)
1222     {
1223       pos_x -= 192;
1224     }
1225     else if(le_move_left_bt->get_state() == BUTTON_HOVER)
1226     {
1227       pos_x -= 64;
1228     }
1229
1230     if(le_move_right_bt->get_state() == BUTTON_PRESSED)
1231     {
1232       pos_x += 192;
1233     }
1234     else if(le_move_right_bt->get_state() == BUTTON_HOVER)
1235     {
1236       pos_x += 64;
1237     }
1238   }
1239
1240 }
1241
1242 void le_highlight_selection()
1243 {
1244   int x1, x2, y1, y2;
1245
1246   if(selection.x1 < selection.x2)
1247   {
1248     x1 = selection.x1;
1249     x2 = selection.x2;
1250   }
1251   else
1252   {
1253     x1 = selection.x2;
1254     x2 = selection.x1;
1255   }
1256   if(selection.y1 < selection.y2)
1257   {
1258     y1 = selection.y1;
1259     y2 = selection.y2;
1260   }
1261   else
1262   {
1263     y1 = selection.y2;
1264     y2 = selection.y1;
1265   }
1266
1267   x1 /= 32;
1268   x2 /= 32;
1269   y1 /= 32;
1270   y2 /= 32;
1271
1272   fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1273 }
1274
1275 void le_change(float x, float y, int tm, unsigned int c)
1276 {
1277   if(le_current_level != NULL)
1278   {
1279     int xx,yy;
1280     int x1, x2, y1, y2;
1281     unsigned int i;
1282
1283     /*  level_changed = true; */
1284
1285     switch(le_selection_mode)
1286     {
1287     case CURSOR:
1288       le_current_level->change(x,y,tm,c);
1289
1290       base_type cursor_base;
1291       cursor_base.x = x;
1292       cursor_base.y = y;
1293       cursor_base.width = 32;
1294       cursor_base.height = 32;
1295
1296       /* if there is a bad guy over there, remove it */
1297       for(i = 0; i < le_world.bad_guys.size(); ++i)
1298         if(rectcollision(cursor_base,le_world.bad_guys[i].base))
1299         {
1300           le_world.bad_guys.erase(le_world.bad_guys.begin() + i);
1301           le_current_level->badguy_data.erase(le_current_level->badguy_data.begin() + i);
1302           }
1303
1304       break;
1305     case SQUARE:
1306       if(selection.x1 < selection.x2)
1307       {
1308         x1 = selection.x1;
1309         x2 = selection.x2;
1310       }
1311       else
1312       {
1313         x1 = selection.x2;
1314         x2 = selection.x1;
1315       }
1316       if(selection.y1 < selection.y2)
1317       {
1318         y1 = selection.y1;
1319         y2 = selection.y2;
1320       }
1321       else
1322       {
1323         y1 = selection.y2;
1324         y2 = selection.y1;
1325       }
1326
1327       x1 /= 32;
1328       x2 /= 32;
1329       y1 /= 32;
1330       y2 /= 32;
1331
1332       /* if there is a bad guy over there, remove it */
1333       for(std::vector<BadGuy>::iterator i = le_world.bad_guys.begin();
1334           i != le_world.bad_guys.end(); /* will be at end of loop */)
1335       {
1336         if(i->base.x/32 >= x1 && i->base.x/32 <= x2
1337             && i->base.y/32 >= y1 && i->base.y/32 <= y2)
1338         {
1339           i = le_world.bad_guys.erase(i);
1340           continue;
1341         }
1342         else
1343         {
1344           ++i;
1345         }
1346       }
1347
1348       for(xx = x1; xx <= x2; xx++)
1349         for(yy = y1; yy <= y2; yy++)
1350         {
1351           le_current_level->change(xx*32, yy*32, tm, c);
1352
1353         }
1354       break;
1355     default:
1356       break;
1357     }
1358   }
1359 }
1360
1361 void le_testlevel()
1362 {
1363   le_current_level->save("test", le_level);
1364
1365   GameSession session("test",le_level, ST_GL_TEST);
1366   session.run();
1367   player_status.reset();
1368
1369   music_manager->halt_music();
1370
1371   Menu::set_current(leveleditor_menu);
1372   le_world.arrays_free();
1373   le_current_level->load_gfx();
1374   le_world.activate_bad_guys();
1375 }
1376
1377 void le_showhelp()
1378 {
1379   SDL_Event event;
1380   unsigned int i, done_;
1381   char *text[] = {
1382                    "  - This is SuperTux's built-in level editor -",
1383                    "It has been designed to be light and easy to use from the start.",
1384                    "",
1385                    "When you first load the level editor you are given a menu where you",
1386                    "can load level subsets, create a new level subset, edit the current",
1387                    "subset's settings, or simply quit the editor. You can access this menu",
1388                    "from the level editor at any time by pressing the escape key.",
1389                    "",
1390                    "To your right is your button bar. The center of this contains many",
1391                    "tiles you can use to make your level. To select a tile, click on it",
1392                    "with your left mouse button; your selection will be shown in the",
1393                    "bottom right corner of the button box. Click anywhere on your level",
1394                    "with the left mouse button to place that tile down. If you right click",
1395                    "a tile in the button bar, you can find out what its keyboard shortcut",
1396                    "is. The three buttons FGD, BGD and EMY let you pick from foreground,",
1397                    "background, and enemy tiles. The eraser lets you remove tiles.",
1398                    "The left and right arrow keys scroll back and forth through your level.",
1399                    "The button with the wrench and screwdriver, lets you change the",
1400                    "settings of your level, including how long it is or what music it will",
1401                    "play. When you are ready to give your level a test, click on the little",
1402                    "running Tux. If you like the changes you have made to your level,",
1403                    "press the red save key to keep them.",
1404                    "To change which level in your subset you are editing, press the white",
1405                    "up and down arrow keys at the top of the button box.",
1406                    "",
1407                    "Have fun making levels! If you make some good ones, send them to us on",
1408                    "the SuperTux mailing list!",
1409                    "- SuperTux team"
1410                  };
1411
1412
1413   blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1414
1415   for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1416     white_small_text->draw(text[i], 5, 80+(i*white_small_text->h), 1);
1417
1418   gold_text->drawf("Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
1419
1420   flipscreen();
1421
1422   done_ = 0;
1423
1424   while(done_ == 0)
1425   {
1426     done_ = wait_for_event(event);
1427     SDL_Delay(50);
1428   }
1429 }