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