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