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