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