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