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