e23cd1f1738a546f5e3120d2055ae1c625000754
[supertux.git] / src / leveleditor.c
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 - February 1st, 2004 */
11
12 /* leveleditor.c - A built-in level editor for SuperTux
13  by Ricardo Cruz <rick2@aeiou.pt>                      */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <SDL.h>
21 #include <SDL_image.h>
22 #include "leveleditor.h"
23
24 #include "screen.h"
25 #include "defines.h"
26 #include "globals.h"
27 #include "setup.h"
28 #include "menu.h"
29 #include "level.h"
30 #include "badguy.h"
31 #include "scene.h"
32 #include "button.h"
33
34 /* definitions to aid development */
35 #define DONE_LEVELEDITOR 1
36 #define DONE_QUIT        2
37 #define DONE_CHANGELEVEL 3
38
39 /* definitions that affect gameplay */
40 #define KEY_CURSOR_SPEED 32
41 #define KEY_CURSOR_FASTSPEED 64
42
43 /* when pagedown/up pressed speed:*/
44 #define PAGE_CURSOR_SPEED 13*32
45
46 #define MOUSE_LEFT_MARGIN 80
47 #define MOUSE_RIGHT_MARGIN (560-32)
48 /* right_margin should noticed that the cursor is 32 pixels,
49    so it should subtract that value */
50 #define MOUSE_POS_SPEED 20
51
52 /* look */
53 #define SELECT_W 2 // size of the selections lines
54 #define SELECT_CLR 0, 255, 0, 255  // lines color (R, G, B, A)
55
56 /* gameloop funcs declerations */
57
58 void loadshared(void);
59 void unloadshared(void);
60
61 /* own declerations */
62 /* crutial ones (main loop) */
63 int le_init();
64 void le_quit();
65 void le_drawlevel();
66 void le_drawinterface();
67 void le_checkevents();
68 void le_change(float x, float y, unsigned char c);
69 void le_testlevel();
70 void le_showhelp();
71 void le_set_defaults(void);
72 void le_activate_bad_guys(void);
73 void le_new_subset(char *subset_name);
74
75 void le_highlight_selection();
76
77 void apply_level_settings_menu();
78 void update_subset_settings_menu();
79 void save_subset_settings_menu();
80 void le_update_buttons(char*);
81
82 /* leveleditor internals */
83 static string_list_type level_subsets;
84 static int le_level_changed;  /* if changes, ask for saving, when quiting*/
85 static int pos_x, cursor_x, cursor_y, cursor_tile, fire;
86 static int le_level;
87 static st_level* le_current_level;
88 static st_subset le_level_subset;
89 static int le_show_grid;
90 static int le_frame;
91 static texture_type le_selection;
92 static int done;
93 static char le_current_tile;
94 static int le_mouse_pressed[2];
95 static button_type le_save_level_bt;
96 static button_type le_test_level_bt;
97 static button_type le_next_level_bt;
98 static button_type le_previous_level_bt;
99 static button_type le_move_right_bt;
100 static button_type le_move_left_bt;
101 static button_type le_rubber_bt;
102 static button_type le_select_mode_one_bt;
103 static button_type le_select_mode_two_bt;
104 static button_type le_settings_bt;
105 static button_type le_bad_bt;
106 static button_type le_bkgd_bt;
107 static button_type le_fgd_bt;
108 static button_panel_type le_bkgd_panel;
109 static button_panel_type le_fgd_panel;
110 static button_panel_type le_bad_panel;
111 static menu_type leveleditor_menu;
112 static menu_type subset_load_menu;
113 static menu_type subset_new_menu;
114 static menu_type subset_settings_menu;
115 static menu_type level_settings_menu;
116
117 static square selection;
118 static int le_selection_mode;
119 static SDL_Event event;
120
121 void le_activate_bad_guys(void)
122 {
123   int x,y;
124
125   /* Activate bad guys: */
126
127   /* as oposed to the gameloop.c func, this one doesn't remove
128   the badguys from tiles                                    */
129
130   for (y = 0; y < 15; ++y)
131     for (x = 0; x < le_current_level->width; ++x)
132       if (le_current_level->tiles[y][x] >= '0' && le_current_level->tiles[y][x] <= '9')
133         add_bad_guy(x * 32, y * 32, le_current_level->tiles[y][x] - '0');
134 }
135
136 void le_set_defaults()
137 {
138   if(le_current_level != NULL)
139     {
140       /* Set defaults: */
141
142       if(le_current_level->time_left == 0)
143         le_current_level->time_left = 255;
144     }
145 }
146
147 int leveleditor(int levelnb)
148 {
149   int last_time, now_time, i;
150
151   le_level = levelnb;
152   if(le_init() != 0)
153     return 1;
154
155   /* Clear screen: */
156
157   clearscreen(0, 0, 0);
158   updatescreen();
159
160   while (SDL_PollEvent(&event))
161   {}
162
163   while(YES)
164     {
165       last_time = SDL_GetTicks();
166       le_frame++;
167
168       le_checkevents();
169
170       if(le_current_level != NULL)
171         {
172           /* making events results to be in order */
173           if(pos_x < 0)
174             pos_x = 0;
175           if(pos_x > (le_current_level->width * 32) - screen->w)
176             pos_x = (le_current_level->width * 32) - screen->w;
177
178           /* draw the level */
179           le_drawlevel();
180         }
181       else
182         clearscreen(0, 0, 0);
183
184       /* draw editor interface */
185       le_drawinterface();
186
187       if(show_menu)
188         {
189           menu_process_current();
190           if(current_menu == &leveleditor_menu)
191             {
192               switch (menu_check(&leveleditor_menu))
193                 {
194                 case 2:
195                   show_menu = NO;
196                   break;
197                 case 3:
198                   update_subset_settings_menu();
199                   break;
200                 case 7:
201                   done = DONE_LEVELEDITOR;
202                   break;
203                 }
204             }
205           else if(current_menu == &level_settings_menu)
206             {
207               switch (menu_check(&level_settings_menu))
208                 {
209                 case 13:
210                   apply_level_settings_menu();
211                   menu_set_current(&leveleditor_menu);
212                   break;
213                 default:
214                   show_menu = YES;
215                   break;
216                 }
217             }
218           else if(current_menu == &subset_load_menu)
219             {
220               switch (i = menu_check(&subset_load_menu))
221                 {
222                 case 0:
223                   break;
224                 default:
225                   if(i != -1)
226                     {
227                       subset_load(&le_level_subset,level_subsets.item[i-2]);
228                       leveleditor_menu.item[3].kind = MN_GOTO;
229                       le_level = 1;
230                       arrays_init();
231                       loadshared();
232                       le_current_level = (st_level*) malloc(sizeof(st_level));
233                       if(level_load(le_current_level, le_level_subset.name, le_level) != 0)
234                         {
235                           le_quit();
236                           return 1;
237                         }
238                       le_update_buttons(le_current_level->theme);
239                       le_set_defaults();
240                       level_load_gfx(le_current_level);
241                       le_activate_bad_guys();
242                       show_menu = YES;
243                     }
244                   break;
245                 }
246             }
247           else if(current_menu == &subset_new_menu)
248             {
249               if(subset_new_menu.item[2].input[0] == '\0')
250                 subset_new_menu.item[3].kind = MN_DEACTIVE;
251               else
252                 {
253                   subset_new_menu.item[3].kind = MN_ACTION;
254
255                   switch (i = menu_check(&subset_new_menu))
256                     {
257                     case 3:
258                       le_new_subset(subset_new_menu.item[2].input);
259                       subset_load(&le_level_subset,subset_new_menu.item[2].input);
260                       leveleditor_menu.item[3].kind = MN_GOTO;
261                       le_level = 1;
262                       arrays_init();
263                       loadshared();
264                       le_current_level = (st_level*) malloc(sizeof(st_level));
265                       if(level_load(le_current_level, le_level_subset.name, le_level) != 0)
266                         {
267                           le_quit();
268                           return 1;
269                         }
270                       le_update_buttons(le_current_level->theme);
271                       le_set_defaults();
272                       level_load_gfx(le_current_level);
273                       le_activate_bad_guys();
274                       menu_item_change_input(&subset_new_menu.item[2],"");
275                       show_menu = YES;
276                       break;
277                     }
278                 }
279             }
280           else if(current_menu == &subset_settings_menu)
281             {
282               if(strcmp(le_level_subset.title,subset_settings_menu.item[2].input) == 0 && strcmp(le_level_subset.description,subset_settings_menu.item[3].input) == 0  )
283                 subset_settings_menu.item[5].kind = MN_DEACTIVE;
284               else
285                 subset_settings_menu.item[5].kind = MN_ACTION;
286
287               switch (i = menu_check(&subset_settings_menu))
288                 {
289                 case 5:
290                   save_subset_settings_menu();
291                   show_menu = YES;
292                   break;
293                 }
294             }
295         }
296
297       if(done)
298         {
299           le_quit();
300           return 0;
301         }
302
303       if(done == DONE_QUIT)
304         {
305           le_quit();
306           return 1;
307         }
308
309       SDL_Delay(25);
310       now_time = SDL_GetTicks();
311       if (now_time < last_time + FPS)
312         SDL_Delay(last_time + FPS - now_time);  /* delay some time */
313
314       flipscreen();
315     }
316
317   return done;
318 }
319
320 void le_default_level(st_level* plevel)
321 {
322   int i,y;
323   strcpy(plevel->name,"UnNamed");
324   strcpy(plevel->theme,"antarctica");
325   strcpy(plevel->song_title,"Mortimers_chipdisko.mod");
326   strcpy(plevel->bkgd_image,"arctis.png");
327   plevel->width = 21;
328   plevel->time_left = 100;
329   plevel->gravity = 10.;
330   plevel->bkgd_red = 0;
331   plevel->bkgd_green = 0;
332   plevel->bkgd_blue = 0;
333
334   for(i = 0; i < 15; ++i)
335     {
336       plevel->tiles[i] = (unsigned char*) malloc((plevel->width+1)*sizeof(unsigned char));
337       plevel->tiles[i][plevel->width] = (unsigned char) '\0';
338       for(y = 0; y < plevel->width; ++y)
339         plevel->tiles[i][y] = (unsigned char) '.';
340       plevel->tiles[i][plevel->width] = (unsigned char) '\0';
341     }
342 }
343
344 void le_new_subset(char *subset_name)
345 {
346   st_level new_lev;
347   st_subset new_subset;
348   new_subset.name = (char*) malloc((strlen(subset_name)+1)*sizeof(char));
349   strcpy(new_subset.name,subset_name);
350   new_subset.title = (char*) malloc((strlen("Unknown Title")+1)*sizeof(char));
351   strcpy(new_subset.title,"Unknown Title");
352   new_subset.description = (char*) malloc((strlen("No description so far.")+1)*sizeof(char));
353   strcpy(new_subset.description,"No description so far.");
354   subset_save(&new_subset);
355   le_default_level(&new_lev);
356   level_save(&new_lev,subset_name,1);
357 }
358
359 void le_update_buttons(char *theme)
360 {
361   int i;
362   char filename[1024];
363   char pathname[1024];
364   SDLKey key;
365   string_list_type bkgd_files;
366   string_list_type fgd_files;
367
368   sprintf(pathname,"images/themes/%s",theme);
369   bkgd_files =  dfiles(pathname,"bkgd-", NULL);
370   string_list_sort(&bkgd_files);
371
372   le_bkgd_panel.hidden = YES;
373   key = SDLK_a;
374   for(i = 0; i < bkgd_files.num_items; ++i)
375     {
376       sprintf(filename,"%s/%s",pathname,bkgd_files.item[i]);
377       button_change_icon(&le_bkgd_panel.item[i],filename);
378     }
379
380   sprintf(pathname,"images/themes/%s",theme);
381   fgd_files =  dfiles(pathname,"solid", NULL);
382   string_list_sort(&fgd_files);
383   key = SDLK_a;
384   for(i = 0; i < fgd_files.num_items; ++i)
385     {
386       sprintf(filename,"%s/%s",pathname,fgd_files.item[i]);
387       button_change_icon(&le_fgd_panel.item[i],filename);
388     }
389
390   string_list_free(&fgd_files);
391   fgd_files =  dfiles(pathname,"brick", NULL);
392   string_list_sort(&fgd_files);
393
394   for(i = 0; i < fgd_files.num_items; ++i)
395     {
396       sprintf(filename,"%s/%s",pathname,fgd_files.item[i]);
397       button_change_icon(&le_fgd_panel.item[i+14],filename);
398     }
399 }
400
401 int le_init()
402 {
403   int i,j;
404   char str[80];
405   char filename[1024];
406   SDLKey key;
407   string_list_type fgd_files;
408   string_list_type bkgd_files;
409   string_list_type bad_files;
410   level_subsets = dsubdirs("/levels", "info");
411
412   le_show_grid = YES;
413
414   /*  level_changed = NO;*/
415   fire = DOWN;
416   done = 0;
417   le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
418   le_level_changed = NO;
419
420   subset_init(&le_level_subset);
421
422   le_current_level = NULL;
423
424   le_current_tile = '.';
425   le_mouse_pressed[LEFT] = NO;
426   le_mouse_pressed[RIGHT] = NO;
427
428   texture_load(&le_selection,DATA_PREFIX "/images/leveleditor/select.png", USE_ALPHA);
429
430   /* Load buttons */
431   button_load(&le_save_level_bt,"/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
432   button_load(&le_next_level_bt,"/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
433   button_load(&le_previous_level_bt,"/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
434   button_load(&le_rubber_bt,"/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
435   button_load(&le_select_mode_one_bt,"/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
436   button_load(&le_select_mode_two_bt,"/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64);
437   button_load(&le_test_level_bt,"/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
438   button_load(&le_settings_bt,"/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
439   button_load(&le_move_left_bt,"/images/icons/left.png","Move left",SDLK_LEFT,0,0);
440   button_load(&le_move_right_bt,"/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
441   button_load(&le_fgd_bt,"/images/icons/fgd.png","Foreground tiles", SDLK_F7,screen->w-64,82);
442   button_load(&le_bkgd_bt,"/images/icons/bgd.png","Background tiles", SDLK_F8,screen->w-43,82);
443   button_load(&le_bad_bt,"/images/icons/bad.png","Bad guys", SDLK_F9,screen->w-22,82);
444
445   bkgd_files =  dfiles("images/themes/antarctica","bkgd-", NULL);
446   string_list_sort(&bkgd_files);
447
448   button_panel_init(&le_bkgd_panel, screen->w - 64,98, 64, 318);
449   le_bkgd_panel.hidden = YES;
450   key = SDLK_a;
451   for(i = 0; i < bkgd_files.num_items; ++i)
452     {
453       sprintf(filename,"images/themes/antarctica/%s",bkgd_files.item[i]);
454       button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i),0,0),i);
455     }
456
457   string_list_free(&bkgd_files);
458   bkgd_files = dfiles("images/shared","cloud-", NULL);
459   string_list_sort(&bkgd_files);
460
461   for(i = 0; i < bkgd_files.num_items; ++i)
462     {
463       sprintf(filename,"images/shared/%s",bkgd_files.item[i]);
464       button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i+8),0,0),i+8);
465     }
466
467   fgd_files =  dfiles("images/themes/antarctica","solid", NULL);
468   string_list_sort(&fgd_files);
469   key = SDLK_a;
470   button_panel_init(&le_fgd_panel, screen->w - 64,98, 64, 318);
471   for(i = 0; i < fgd_files.num_items; ++i)
472     {
473       sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]);
474       button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i),0,0),i);
475     }
476
477   string_list_free(&fgd_files);
478   string_list_add_item(&fgd_files,"waves-0.png");
479   string_list_add_item(&fgd_files,"water.png");
480   string_list_add_item(&fgd_files,"pole.png");
481   string_list_add_item(&fgd_files,"poletop.png");
482   string_list_add_item(&fgd_files,"flag-0.png");
483   string_list_add_item(&fgd_files,"box-empty.png");
484   string_list_add_item(&fgd_files,"mints.png");
485   string_list_add_item(&fgd_files,"distro-0.png");
486   string_list_add_item(&fgd_files,"golden-herring.png");
487   string_list_add_item(&fgd_files,"distro-0.png");
488
489   for(i = 0; i < fgd_files.num_items; ++i)
490     {
491       sprintf(filename,"images/shared/%s",fgd_files.item[i]);
492       button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+4),0,0),i+4);
493     }
494
495   string_list_free(&fgd_files);
496   fgd_files =  dfiles("images/themes/antarctica","brick", NULL);
497   string_list_sort(&fgd_files);
498
499   for(i = 0; i < fgd_files.num_items; ++i)
500     {
501       sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]);
502       button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+14),0,0),i+14);
503     }
504
505   string_list_free(&fgd_files);
506   string_list_add_item(&fgd_files,"distro-0.png");
507   string_list_add_item(&fgd_files,"distro-0.png");
508   for(i = 0; i < fgd_files.num_items; ++i)
509     {
510       sprintf(filename,"images/shared/%s",fgd_files.item[i]);
511       button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+16),0,0),i+16);
512     }
513
514   le_fgd_panel.item[10].bkgd = &le_fgd_panel.item[9].icon;
515   le_fgd_panel.item[11].bkgd = &le_fgd_panel.item[9].icon;
516   le_fgd_panel.item[12].bkgd = &le_fgd_panel.item[9].icon;
517   le_fgd_panel.item[16].bkgd = &le_fgd_panel.item[14].icon;
518   le_fgd_panel.item[17].bkgd = &le_fgd_panel.item[15].icon;
519
520   bad_files;
521   string_list_init(&bad_files);
522   string_list_add_item(&bad_files,"bsod-left-0.png");
523   string_list_add_item(&bad_files,"laptop-left-0.png");
524   string_list_add_item(&bad_files,"bag-left-0.png");
525   button_panel_init(&le_bad_panel, screen->w - 64,98, 64, 318);
526   le_bad_panel.hidden = YES;
527   key = SDLK_a;
528   for(i = 0; i < bad_files.num_items; ++i)
529     {
530       sprintf(filename,"images/shared/%s",bad_files.item[i]);
531       button_panel_additem(&le_bad_panel,button_create(filename, "Bad Guy",(SDLKey)((int)key+i),0,0),i);
532     }
533
534   menu_init(&leveleditor_menu);
535   menu_additem(&leveleditor_menu,menu_item_create(MN_LABEL,"Level Editor Menu",0,0));
536   menu_additem(&leveleditor_menu,menu_item_create(MN_HL,"",0,0));
537   menu_additem(&leveleditor_menu,menu_item_create(MN_ACTION,"Return To Level Editor",0,0));
538   menu_additem(&leveleditor_menu,menu_item_create(MN_DEACTIVE,"Level Subset Settings",0,&subset_settings_menu));
539   menu_additem(&leveleditor_menu,menu_item_create(MN_GOTO,"Load Level Subset",0,&subset_load_menu));
540   menu_additem(&leveleditor_menu,menu_item_create(MN_GOTO,"New Level Subset",0,&subset_new_menu));
541   menu_additem(&leveleditor_menu,menu_item_create(MN_HL,"",0,0));
542   menu_additem(&leveleditor_menu,menu_item_create(MN_ACTION,"Quit Level Editor",0,0));
543
544   menu_reset();
545   menu_set_current(&leveleditor_menu);
546   show_menu = YES;
547
548   menu_init(&subset_load_menu);
549   menu_additem(&subset_load_menu,menu_item_create(MN_LABEL,"Load Level Subset",0,0));
550   menu_additem(&subset_load_menu,menu_item_create(MN_HL,"",0,0));
551   for(i = 0; i < level_subsets.num_items; ++i)
552     {
553       menu_additem(&subset_load_menu,menu_item_create(MN_ACTION,level_subsets.item[i],0,0));
554     }
555   menu_additem(&subset_load_menu,menu_item_create(MN_HL,"",0,0));
556   menu_additem(&subset_load_menu,menu_item_create(MN_BACK,"Back",0,0));
557
558   menu_init(&subset_new_menu);
559   menu_additem(&subset_new_menu,menu_item_create(MN_LABEL,"New Level Subset",0,0));
560   menu_additem(&subset_new_menu,menu_item_create(MN_HL,"",0,0));
561   menu_additem(&subset_new_menu,menu_item_create(MN_TEXTFIELD,"Enter Name",0,0));
562   menu_additem(&subset_new_menu,menu_item_create(MN_ACTION,"Create",0,0));
563   menu_additem(&subset_new_menu,menu_item_create(MN_HL,"",0,0));
564   menu_additem(&subset_new_menu,menu_item_create(MN_BACK,"Back",0,0));
565
566   menu_init(&subset_settings_menu);
567   menu_additem(&subset_settings_menu,menu_item_create(MN_LABEL,"Level Subset Settings",0,0));
568   menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0));
569   menu_additem(&subset_settings_menu,menu_item_create(MN_TEXTFIELD,"Title",0,0));
570   menu_additem(&subset_settings_menu,menu_item_create(MN_TEXTFIELD,"Description",0,0));
571   menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0));
572   menu_additem(&subset_settings_menu,menu_item_create(MN_ACTION,"Save Changes",0,0));
573   menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0));
574   menu_additem(&subset_settings_menu,menu_item_create(MN_BACK,"Back",0,0));
575
576   menu_init(&level_settings_menu);
577   level_settings_menu.arrange_left = YES;
578   menu_additem(&level_settings_menu,menu_item_create(MN_LABEL,"Level Settings",0,0));
579   menu_additem(&level_settings_menu,menu_item_create(MN_HL,"",0,0));
580   menu_additem(&level_settings_menu,menu_item_create(MN_TEXTFIELD,"Name    ",0,0));
581   menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Theme   ",0,0));
582   menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Song    ",0,0));
583   menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Bg-Image",0,0));
584   menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Length ",0,0));
585   menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Time   ",0,0));
586   menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Gravity",0,0));
587   menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Red    ",0,0));
588   menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Green  ",0,0));
589   menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Blue   ",0,0));
590   menu_additem(&level_settings_menu,menu_item_create(MN_HL,"",0,0));
591   menu_additem(&level_settings_menu,menu_item_create(MN_ACTION,"Apply Changes",0,0));
592
593   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
594
595   return 0;
596 }
597
598 void update_level_settings_menu()
599 {
600   char str[80];
601   int i;
602
603   menu_item_change_input(&level_settings_menu.item[2], le_current_level->name);
604   sprintf(str,"%d",le_current_level->width);
605
606   string_list_copy(level_settings_menu.item[3].list, dsubdirs("images/themes", "solid0.png"));
607   string_list_copy(level_settings_menu.item[4].list, dfiles("music/",NULL, "-fast"));
608   string_list_copy(level_settings_menu.item[5].list, dfiles("images/background",NULL, NULL));
609   if((i = string_list_find(level_settings_menu.item[3].list,le_current_level->theme)) != -1)
610     level_settings_menu.item[3].list->active_item = i;
611   if((i = string_list_find(level_settings_menu.item[4].list,le_current_level->song_title)) != -1)
612     level_settings_menu.item[4].list->active_item = i;
613   if((i = string_list_find(level_settings_menu.item[5].list,le_current_level->bkgd_image)) != -1)
614     level_settings_menu.item[5].list->active_item = i;
615
616   menu_item_change_input(&level_settings_menu.item[6], str);
617   sprintf(str,"%d",le_current_level->time_left);
618   menu_item_change_input(&level_settings_menu.item[7], str);
619   sprintf(str,"%2.0f",le_current_level->gravity);
620   menu_item_change_input(&level_settings_menu.item[8], str);
621   sprintf(str,"%d",le_current_level->bkgd_red);
622   menu_item_change_input(&level_settings_menu.item[9], str);
623   sprintf(str,"%d",le_current_level->bkgd_green);
624   menu_item_change_input(&level_settings_menu.item[10], str);
625   sprintf(str,"%d",le_current_level->bkgd_blue);
626   menu_item_change_input(&level_settings_menu.item[11], str);
627 }
628
629 void update_subset_settings_menu()
630 {
631   menu_item_change_input(&subset_settings_menu.item[2], le_level_subset.title);
632   menu_item_change_input(&subset_settings_menu.item[3], le_level_subset.description);
633 }
634
635 void apply_level_settings_menu()
636 {
637   int i,y,j;
638   i = NO;
639
640   strcpy(le_current_level->name,level_settings_menu.item[2].input);
641
642   if(strcmp(le_current_level->bkgd_image,string_list_active(level_settings_menu.item[5].list)) != 0)
643     {
644       strcpy(le_current_level->bkgd_image,string_list_active(level_settings_menu.item[5].list));
645       i = YES;
646     }
647
648   if(strcmp(le_current_level->theme,string_list_active(level_settings_menu.item[3].list)) != 0)
649     {
650       strcpy(le_current_level->theme,string_list_active(level_settings_menu.item[3].list));
651       le_update_buttons(le_current_level->theme);
652       i = YES;
653     }
654
655   if(i == YES)
656     {
657       level_free_gfx();
658       level_load_gfx(le_current_level);
659     }
660
661   strcpy(le_current_level->song_title,string_list_active(level_settings_menu.item[4].list));
662
663   i = le_current_level->width;
664   le_current_level->width = atoi(level_settings_menu.item[6].input);
665   if(le_current_level->width < i)
666     {
667       if(le_current_level->width < 21)
668         le_current_level->width = 21;
669       for(y = 0; y < 15; ++y)
670         {
671           le_current_level->tiles[y] = (unsigned char*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned char));
672           le_current_level->tiles[y][le_current_level->width] = (unsigned char) '\0';
673         }
674     }
675   else if(le_current_level->width > i)
676     {
677       for(y = 0; y < 15; ++y)
678         {
679           le_current_level->tiles[y] = (unsigned char*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned char));
680           for(j = 0; j < le_current_level->width - i; ++j)
681             le_current_level->tiles[y][i+j] = (unsigned char) '.';
682           le_current_level->tiles[y][le_current_level->width] = (unsigned char) '\0';
683         }
684     }
685   le_current_level->time_left = atoi(level_settings_menu.item[7].input);
686   le_current_level->gravity = atof(level_settings_menu.item[8].input);
687   le_current_level->bkgd_red = atoi(level_settings_menu.item[9].input);
688   le_current_level->bkgd_green = atoi(level_settings_menu.item[10].input);
689   le_current_level->bkgd_blue = atoi(level_settings_menu.item[11].input);
690 }
691
692 void save_subset_settings_menu()
693 {
694   free(le_level_subset.title);
695   le_level_subset.title = (char*) malloc(sizeof(char)*(strlen(subset_settings_menu.item[2].input)+1));
696   strcpy(le_level_subset.title,subset_settings_menu.item[2].input);
697   free(le_level_subset.description);
698   le_level_subset.description = (char*) malloc(sizeof(char)*(strlen(subset_settings_menu.item[3].input)+1));
699   strcpy(le_level_subset.description,subset_settings_menu.item[3].input);
700   subset_save(&le_level_subset);
701 }
702
703 void le_goto_level(int levelnb)
704 {
705   arrays_free();
706   arrays_init();
707
708   level_free(le_current_level);
709   if(level_load(le_current_level, le_level_subset.name, levelnb) != 0)
710     {
711       level_load(le_current_level, le_level_subset.name, le_level);
712     }
713   else
714     {
715       le_level = levelnb;
716     }
717
718   le_set_defaults();
719
720   le_update_buttons(le_current_level->theme);
721
722   level_free_gfx();
723   level_load_gfx(le_current_level);
724
725   le_activate_bad_guys();
726 }
727
728 void le_quit(void)
729 {
730   /*if(level_changed == YES)
731     if(askforsaving() == CANCEL)
732       return;*/ //FIXME
733
734   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
735
736   texture_free(&le_selection);
737   menu_free(&leveleditor_menu);
738   menu_free(&subset_load_menu);
739   menu_free(&subset_new_menu);
740   menu_free(&subset_settings_menu);
741   menu_free(&level_settings_menu);
742   button_panel_free(&le_bkgd_panel);
743   button_panel_free(&le_fgd_panel);
744   button_panel_free(&le_bad_panel);
745   button_free(&le_save_level_bt);
746   button_free(&le_test_level_bt);
747   button_free(&le_next_level_bt);
748   button_free(&le_previous_level_bt);
749   button_free(&le_move_right_bt);
750   button_free(&le_move_left_bt);
751   button_free(&le_rubber_bt);
752   button_free(&le_select_mode_one_bt);
753   button_free(&le_select_mode_two_bt);
754   button_free(&le_settings_bt);
755   button_free(&le_bad_bt);
756   button_free(&le_bkgd_bt);
757   button_free(&le_fgd_bt);
758
759   if(le_current_level != NULL)
760     {
761       level_free_gfx();
762       level_free(le_current_level);
763       unloadshared();
764       arrays_free();
765     }
766 }
767
768 void le_drawinterface()
769 {
770   int x,y;
771   char str[80];
772
773   if(le_current_level != NULL)
774     {
775       /* draw a grid (if selected) */
776       if(le_show_grid)
777         {
778           for(x = 0; x < 19; x++)
779             fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
780           for(y = 0; y < 15; y++)
781             fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
782         }
783     }
784
785   if(le_selection_mode == CURSOR)
786     texture_draw(&le_selection, cursor_x - pos_x, cursor_y, NO_UPDATE);
787   else if(le_selection_mode == SQUARE)
788     {
789       int w, h;
790       le_highlight_selection();
791       /* draw current selection */
792       w = selection.x2 - selection.x1;
793       h = selection.y2 - selection.y1;
794       fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
795       fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
796       fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
797       fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
798     }
799
800
801   /* draw button bar */
802   fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
803   drawshape(19 * 32, 14 * 32, le_current_tile);
804   switch(le_current_tile)
805     {
806     case 'B':
807       texture_draw(&img_mints, 19 * 32, 14 * 32, NO_UPDATE);
808       break;
809     case '!':
810       texture_draw(&img_golden_herring,19 * 32, 14 * 32, NO_UPDATE);
811       break;
812     case 'x':
813     case 'y':
814     case 'A':
815       texture_draw(&img_distro[(le_frame / 5) % 4], 19 * 32, 14 * 32, NO_UPDATE);
816       break;
817     case '0':
818       texture_draw(&img_bsod_left[(le_frame / 5) % 4],19 * 32, 14 * 32, NO_UPDATE);
819       break;
820     case '1':
821       texture_draw(&img_laptop_left[(le_frame / 5) % 3],19 * 32, 14 * 32, NO_UPDATE);
822       break;
823     case '2':
824       texture_draw(&img_money_left[0],19 * 32, 14 * 32, NO_UPDATE);
825       break;
826     default:
827       break;
828     }
829
830   if(le_current_level != NULL)
831     {
832       button_draw(&le_save_level_bt);
833       button_draw(&le_test_level_bt);
834       button_draw(&le_next_level_bt);
835       button_draw(&le_previous_level_bt);
836       button_draw(&le_rubber_bt);
837       button_draw(&le_select_mode_one_bt);
838       button_draw(&le_select_mode_two_bt);
839       button_draw(&le_settings_bt);
840       button_draw(&le_move_right_bt);
841       button_draw(&le_move_left_bt);
842       button_draw(&le_bad_bt);
843       button_draw(&le_bkgd_bt);
844       button_draw(&le_fgd_bt);
845       button_panel_draw(&le_bkgd_panel);
846       button_panel_draw(&le_fgd_panel);
847       button_panel_draw(&le_bad_panel);
848
849       sprintf(str, "%d/%d", le_level,le_level_subset.levels);
850       text_drawf(&white_text, str, -8, 16, A_RIGHT, A_NONE, 1, NO_UPDATE);
851
852       text_draw(&white_small_text, "F1 for Help", 10, 430, 1, NO_UPDATE);
853     }
854   else
855     {
856       if(show_menu == NO)
857         text_draw(&white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1, NO_UPDATE);
858       else
859         text_draw(&white_small_text, "No Level Subset loaded", 10, 430, 1, NO_UPDATE);
860     }
861
862 }
863
864 void le_drawlevel()
865 {
866   int y,x,i,s;
867   static char str[LEVEL_NAME_MAX];
868
869   /* Draw the real background */
870   if(le_current_level->bkgd_image[0] != '\0')
871     {
872       s = pos_x / 30;
873       texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s - 32, img_bkgd.h, NO_UPDATE);
874       texture_draw_part(&img_bkgd,0,0,screen->w - s - 32 ,0,s,img_bkgd.h, NO_UPDATE);
875     }
876   else
877     {
878       clearscreen(le_current_level->bkgd_red, le_current_level->bkgd_green, le_current_level->bkgd_blue);
879     }
880
881   /*       clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
882
883   for (y = 0; y < 15; ++y)
884     for (x = 0; x < 20; ++x)
885       {
886         drawshape(x * 32 - ((int)pos_x % 32), y * 32, le_current_level->tiles[y][x + (int)(pos_x / 32)]);
887
888         /* draw whats inside stuff when cursor is selecting those */
889         /* (draw them all the time - is this the right behaviour?) */
890         switch(le_current_level->tiles[y][x + (int)(pos_x/32)])
891           {
892           case 'B':
893             texture_draw(&img_mints, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
894             break;
895           case '!':
896             texture_draw(&img_golden_herring, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
897             break;
898           case 'x':
899           case 'y':
900           case 'A':
901             texture_draw(&img_distro[(frame / 5) % 4], x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
902             break;
903           default:
904             break;
905           }
906       }
907
908   /* Draw the Bad guys: */
909   for (i = 0; i < num_bad_guys; ++i)
910     {
911       if(bad_guys[i].base.alive == NO)
912         continue;
913       /* to support frames: img_bsod_left[(frame / 5) % 4] */
914       if(bad_guys[i].kind == BAD_BSOD)
915         texture_draw(&img_bsod_left[(le_frame / 5) % 4], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
916       else if(bad_guys[i].kind == BAD_LAPTOP)
917         texture_draw(&img_laptop_left[(le_frame / 5) % 3], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
918       else if (bad_guys[i].kind == BAD_MONEY)
919         texture_draw(&img_money_left[(le_frame / 5) % 2], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
920     }
921
922
923   /* Draw the player: */
924   /* for now, the position is fixed at (0, 240) */
925   texture_draw(&tux_right[(frame / 5) % 3], 0 - pos_x, 240, NO_UPDATE);
926 }
927
928 void le_checkevents()
929 {
930   SDLKey key;
931   SDLMod keymod;
932   button_type* pbutton;
933   int x,y;
934
935   keymod = SDL_GetModState();
936
937   while(SDL_PollEvent(&event))
938     {
939       /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
940       if(event.type == SDL_KEYDOWN || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > 0 && event.motion.x < screen->w - 64 &&
941                                        event.motion.y > 0 && event.motion.y < screen->h)))
942         {
943
944           switch(event.type)
945             {
946             case SDL_KEYDOWN:   // key pressed
947               key = event.key.keysym.sym;
948               if(show_menu)
949                 {
950                   menu_event(&event.key.keysym);
951                   if(key == SDLK_ESCAPE)
952                     {
953                       show_menu = NO;
954                       menu_set_current(&leveleditor_menu);
955                     }
956                   break;
957                 }
958               switch(key)
959                 {
960                 case SDLK_ESCAPE:
961                   if(!show_menu)
962                     show_menu = YES;
963                   else
964                     show_menu = NO;
965                   break;
966                 case SDLK_LEFT:
967                   if(fire == DOWN)
968                     cursor_x -= KEY_CURSOR_SPEED;
969                   else
970                     cursor_x -= KEY_CURSOR_FASTSPEED;
971
972                   if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
973                     pos_x = cursor_x - MOUSE_LEFT_MARGIN;
974
975                   break;
976                 case SDLK_RIGHT:
977                   if(fire == DOWN)
978                     cursor_x += KEY_CURSOR_SPEED;
979                   else
980                     cursor_x += KEY_CURSOR_FASTSPEED;
981
982                   if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
983                     pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
984
985                   break;
986                 case SDLK_UP:
987                   if(fire == DOWN)
988                     cursor_y -= KEY_CURSOR_SPEED;
989                   else
990                     cursor_y -= KEY_CURSOR_FASTSPEED;
991
992                   if(cursor_y < 0)
993                     cursor_y = 0;
994                   break;
995                 case SDLK_DOWN:
996                   if(fire == DOWN)
997                     cursor_y += KEY_CURSOR_SPEED;
998                   else
999                     cursor_y += KEY_CURSOR_FASTSPEED;
1000
1001                   if(cursor_y > screen->h-32)
1002                     cursor_y = screen->h-32;
1003                   break;
1004                 case SDLK_LCTRL:
1005                   fire =UP;
1006                   break;
1007                 case SDLK_F1:
1008                   le_showhelp();
1009                   break;
1010                 case SDLK_HOME:
1011                   cursor_x = 0;
1012                   pos_x = cursor_x;
1013                   break;
1014                 case SDLK_END:
1015                   cursor_x = (le_current_level->width * 32) - 32;
1016                   pos_x = cursor_x;
1017                   break;
1018                 case SDLK_F9:
1019                   le_show_grid = !le_show_grid;
1020                   break;
1021                 default:
1022                   break;
1023                 }
1024               break;
1025             case SDL_KEYUP:     /* key released */
1026               switch(event.key.keysym.sym)
1027                 {
1028                 case SDLK_LCTRL:
1029                   fire = DOWN;
1030                   break;
1031                 default:
1032                   break;
1033                 }
1034               break;
1035             case SDL_MOUSEBUTTONDOWN:
1036               if(event.button.button == SDL_BUTTON_LEFT)
1037                 {
1038                   le_mouse_pressed[LEFT] = YES;
1039
1040                   selection.x1 = event.motion.x + pos_x;
1041                   selection.y1 = event.motion.y;
1042                   selection.x2 = event.motion.x + pos_x;
1043                   selection.y2 = event.motion.y;
1044                 }
1045               else if(event.button.button == SDL_BUTTON_RIGHT)
1046                 le_mouse_pressed[RIGHT] = YES;
1047               break;
1048             case SDL_MOUSEBUTTONUP:
1049               if(event.button.button == SDL_BUTTON_LEFT)
1050                 le_mouse_pressed[LEFT] = NO;
1051               else if(event.button.button == SDL_BUTTON_RIGHT)
1052                 le_mouse_pressed[RIGHT] = NO;
1053               break;
1054             case SDL_MOUSEMOTION:
1055               if(!show_menu)
1056                 {
1057                   x = event.motion.x;
1058                   y = event.motion.y;
1059
1060                   cursor_x = ((int)(pos_x + x) / 32) * 32;
1061                   cursor_y = ((int) y / 32) * 32;
1062
1063                   if(le_mouse_pressed[LEFT] == YES)
1064                     {
1065                       selection.x2 = x + pos_x;
1066                       selection.y2 = y;
1067                     }
1068
1069                   if(le_mouse_pressed[RIGHT] == YES)
1070                     {
1071                       pos_x += -1 * event.motion.xrel;
1072                     }
1073                 }
1074               break;
1075             case SDL_QUIT:      // window closed
1076               done = DONE_QUIT;
1077               break;
1078             default:
1079               break;
1080             }
1081         }
1082
1083       if(le_current_level != NULL)
1084         {
1085           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 &&
1086               event.motion.y > 0 && event.motion.y < screen->h)))
1087             {
1088               le_mouse_pressed[LEFT] = NO;
1089               le_mouse_pressed[RIGHT] = NO;
1090
1091               if(show_menu == NO)
1092                 {
1093                   /* Check for button events */
1094                   button_event(&le_test_level_bt,&event);
1095                   if(button_get_state(&le_test_level_bt) == BN_CLICKED)
1096                     le_testlevel();
1097                   button_event(&le_save_level_bt,&event);
1098                   if(button_get_state(&le_save_level_bt) == BN_CLICKED)
1099                     level_save(le_current_level,le_level_subset.name,le_level);
1100                   button_event(&le_next_level_bt,&event);
1101                   if(button_get_state(&le_next_level_bt) == BN_CLICKED)
1102                     {
1103                       if(le_level < le_level_subset.levels)
1104                         {
1105                           le_goto_level(++le_level);
1106                         }
1107                       else
1108                         {
1109                           st_level new_lev;
1110                           char str[1024];
1111                           int d = 0;
1112                           sprintf(str,"Level %d doesn't exist.",le_level+1);
1113                           text_drawf(&white_text,str,0,-18,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE);
1114                           text_drawf(&white_text,"Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE);
1115                           text_drawf(&red_text,"(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE);
1116                           flipscreen();
1117                           while(d == 0)
1118                             {
1119                               while(SDL_PollEvent(&event))
1120                                 switch(event.type)
1121                                   {
1122                                   case SDL_KEYDOWN:             // key pressed
1123                                     switch(event.key.keysym.sym)
1124                                       {
1125                                       case SDLK_y:
1126                                         le_default_level(&new_lev);
1127                                         level_save(&new_lev,le_level_subset.name,++le_level);
1128                                         le_level_subset.levels = le_level;
1129                                         le_goto_level(le_level);
1130                                         d = 1;
1131                                         break;
1132                                       case SDLK_n:
1133                                         d = 1;
1134                                         break;
1135                                       }
1136                                     break;
1137                                   default:
1138                                     break;
1139                                   }
1140                               SDL_Delay(50);
1141                             }
1142                         }
1143                     }
1144                   button_event(&le_previous_level_bt,&event);
1145                   if(button_get_state(&le_previous_level_bt) == BN_CLICKED)
1146                     {
1147                       if(le_level > 1)
1148                         le_goto_level(--le_level);
1149                     }
1150                   button_event(&le_rubber_bt,&event);
1151                   if(button_get_state(&le_rubber_bt) == BN_CLICKED)
1152                     le_current_tile = '.';
1153                   button_event(&le_select_mode_one_bt,&event);
1154                   if(button_get_state(&le_select_mode_one_bt) == BN_CLICKED)
1155                     le_selection_mode = CURSOR;
1156                   button_event(&le_select_mode_two_bt,&event);
1157                   if(button_get_state(&le_select_mode_two_bt) == BN_CLICKED)
1158                     le_selection_mode = SQUARE;
1159
1160                   button_event(&le_bad_bt,&event);
1161                   if(button_get_state(&le_bad_bt) == BN_CLICKED)
1162                     {
1163                       le_bad_panel.hidden = NO;
1164                       le_fgd_panel.hidden = YES;
1165                       le_bkgd_panel.hidden = YES;
1166                     }
1167
1168                   button_event(&le_fgd_bt,&event);
1169                   if(button_get_state(&le_fgd_bt) == BN_CLICKED)
1170                     {
1171                       le_bad_panel.hidden = YES;
1172                       le_fgd_panel.hidden = NO;
1173                       le_bkgd_panel.hidden = YES;
1174                     }
1175                   button_event(&le_bkgd_bt,&event);
1176                   if(button_get_state(&le_bkgd_bt) == BN_CLICKED)
1177                     {
1178                       le_bad_panel.hidden = YES;
1179                       le_fgd_panel.hidden = YES;
1180                       le_bkgd_panel.hidden = NO;
1181                     }
1182                   button_event(&le_settings_bt,&event);
1183                   if(button_get_state(&le_settings_bt) == BN_CLICKED)
1184                     {
1185                       if(show_menu == NO)
1186                         {
1187                           update_level_settings_menu();
1188                           menu_set_current(&level_settings_menu);
1189                           show_menu = YES;
1190                         }
1191                       else
1192                         {
1193                           menu_set_current(&leveleditor_menu);
1194                           show_menu = NO;
1195                         }
1196                     }
1197                   if((pbutton = button_panel_event(&le_bkgd_panel,&event)) != NULL)
1198                     {
1199                       if(button_get_state(pbutton) == BN_CLICKED)
1200                         {
1201                           char c = '\0';
1202                           if(pbutton->tag >= 0 && pbutton->tag <= 3)
1203                             c = 'G' + pbutton->tag;
1204                           else if(pbutton->tag >= 4 && pbutton->tag <= 7)
1205                             c = 'g' + pbutton->tag - 4;
1206                           else if(pbutton->tag >= 8 && pbutton->tag <= 11)
1207                             c = 'C' + pbutton->tag - 8;
1208                           else if(pbutton->tag >= 12 && pbutton->tag <= 15)
1209                             c = 'c' + pbutton->tag - 12;
1210                           if(c != '\0')
1211                             le_current_tile = c;
1212                         }
1213                     }
1214                   if((pbutton = button_panel_event(&le_fgd_panel,&event)) != NULL)
1215                     {
1216                       if(button_get_state(pbutton) == BN_CLICKED)
1217                         {
1218                           char c = '\0';
1219                           if(pbutton->tag == 0)
1220                             c = '#' ;
1221                           else if(pbutton->tag == 1)
1222                             c = '[';
1223                           else if(pbutton->tag == 2)
1224                             c = '=';
1225                           else if(pbutton->tag == 3)
1226                             c = ']';
1227                           else if(pbutton->tag == 4)
1228                             c = '^';
1229                           else if(pbutton->tag == 5)
1230                             c = '&';
1231                           else if(pbutton->tag == 6)
1232                             c = '|';
1233                           else if(pbutton->tag == 7)
1234                             c = '*';
1235                           else if(pbutton->tag == 8)
1236                             c = '\\';
1237                           else if(pbutton->tag == 9)
1238                             c = 'a';
1239                           else if(pbutton->tag == 10)
1240                             c = 'B';
1241                           else if(pbutton->tag == 11)
1242                             c = 'A';
1243                           else if(pbutton->tag == 12)
1244                             c = '!';
1245                           else if(pbutton->tag == 13)
1246                             c = '$';
1247                           else if(pbutton->tag == 14)
1248                             c = 'X';
1249                           else if(pbutton->tag == 15)
1250                             c = 'Y';
1251                           else if(pbutton->tag == 16)
1252                             c = 'x';
1253                           else if(pbutton->tag == 17)
1254                             c = 'y';
1255                           if(c != '\0')
1256                             le_current_tile = c;
1257                         }
1258                     }
1259                   if((pbutton = button_panel_event(&le_bad_panel,&event)) != NULL)
1260                     {
1261                       if(button_get_state(pbutton) == BN_CLICKED)
1262                         {
1263                           char c = '\0';
1264                           if(pbutton->tag >= 0 && pbutton->tag <= 2)
1265                             c = '0' + pbutton->tag;
1266                           if(c != '\0')
1267                             le_current_tile = c;
1268                         }
1269                     }
1270                 }
1271               else
1272                 {
1273                   button_event(&le_settings_bt,&event);
1274                   if(button_get_state(&le_settings_bt) == BN_CLICKED)
1275                     {
1276                       if(show_menu == NO)
1277                         {
1278                           update_level_settings_menu();
1279                           menu_set_current(&level_settings_menu);
1280                           show_menu = YES;
1281                         }
1282                       else
1283                         {
1284                           menu_set_current(&leveleditor_menu);
1285                           show_menu = NO;
1286                         }
1287                     }
1288                 }
1289             }
1290           if(show_menu == NO)
1291             {
1292               button_event(&le_move_left_bt,&event);
1293               button_event(&le_move_right_bt,&event);
1294
1295               if(le_mouse_pressed[LEFT])
1296                 {
1297                   le_change(cursor_x, cursor_y, le_current_tile);
1298                 }
1299             }
1300         }
1301     }
1302   if(show_menu == NO)
1303     {
1304       if(button_get_state(&le_move_left_bt) == BN_PRESSED)
1305         {
1306           pos_x -= 192;
1307         }
1308       else if(button_get_state(&le_move_left_bt) == BN_HOVER)
1309         {
1310           pos_x -= 96;
1311         }
1312
1313       if(button_get_state(&le_move_right_bt) == BN_PRESSED)
1314         {
1315           pos_x += 192;
1316         }
1317       else if(button_get_state(&le_move_right_bt) == BN_HOVER)
1318         {
1319           pos_x += 96;
1320         }
1321     }
1322
1323 }
1324
1325 void le_highlight_selection()
1326 {
1327   int x,y,i;
1328   int x1, x2, y1, y2;
1329
1330   if(selection.x1 < selection.x2)
1331     {
1332       x1 = selection.x1;
1333       x2 = selection.x2;
1334     }
1335   else
1336     {
1337       x1 = selection.x2;
1338       x2 = selection.x1;
1339     }
1340   if(selection.y1 < selection.y2)
1341     {
1342       y1 = selection.y1;
1343       y2 = selection.y2;
1344     }
1345   else
1346     {
1347       y1 = selection.y2;
1348       y2 = selection.y1;
1349     }
1350
1351   x1 /= 32;
1352   x2 /= 32;
1353   y1 /= 32;
1354   y2 /= 32;
1355
1356   fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1357 }
1358
1359 void le_change(float x, float y, unsigned char c)
1360 {
1361   if(le_current_level != NULL)
1362     {
1363       int xx,yy,i;
1364       int x1, x2, y1, y2;
1365
1366       /*  level_changed = YES; */
1367
1368       switch(le_selection_mode)
1369         {
1370         case CURSOR:
1371           level_change(le_current_level,x,y,c);
1372
1373           yy = ((int)y / 32);
1374           xx = ((int)x / 32);
1375
1376           /* if there is a bad guy over there, remove it */
1377           for(i = 0; i < num_bad_guys; ++i)
1378             if (bad_guys[i].base.alive)
1379               if(xx == bad_guys[i].base.x/32 && yy == bad_guys[i].base.y/32)
1380                 bad_guys[i].base.alive = NO;
1381
1382           if(c == '0')  /* if it's a bad guy */
1383             add_bad_guy(xx*32, yy*32, BAD_BSOD);
1384           else if(c == '1')
1385             add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1386           else if(c == '2')
1387             add_bad_guy(xx*32, yy*32, BAD_MONEY);
1388
1389           break;
1390         case SQUARE:
1391           if(selection.x1 < selection.x2)
1392             {
1393               x1 = selection.x1;
1394               x2 = selection.x2;
1395             }
1396           else
1397             {
1398               x1 = selection.x2;
1399               x2 = selection.x1;
1400             }
1401           if(selection.y1 < selection.y2)
1402             {
1403               y1 = selection.y1;
1404               y2 = selection.y2;
1405             }
1406           else
1407             {
1408               y1 = selection.y2;
1409               y2 = selection.y1;
1410             }
1411
1412           x1 /= 32;
1413           x2 /= 32;
1414           y1 /= 32;
1415           y2 /= 32;
1416
1417           /* if there is a bad guy over there, remove it */
1418           for(i = 0; i < num_bad_guys; ++i)
1419             if(bad_guys[i].base.alive)
1420               if(bad_guys[i].base.x/32 >= x1 && bad_guys[i].base.x/32 <= x2
1421                   && bad_guys[i].base.y/32 >= y1 && bad_guys[i].base.y/32 <= y2)
1422                 bad_guys[i].base.alive = NO;
1423
1424           for(xx = x1; xx <= x2; xx++)
1425             for(yy = y1; yy <= y2; yy++)
1426               {
1427                 level_change(le_current_level, xx*32, yy*32, c);
1428
1429                 if(c == '0')  // if it's a bad guy
1430                   add_bad_guy(xx*32, yy*32, BAD_BSOD);
1431                 else if(c == '1')
1432                   add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1433                 else if(c == '2')
1434                   add_bad_guy(xx*32, yy*32, BAD_MONEY);
1435               }
1436           break;
1437         default:
1438           break;
1439         }
1440     }
1441 }
1442
1443 void le_testlevel()
1444 {
1445   level_save(le_current_level,"test",le_level);
1446   gameloop("test",le_level, ST_GL_TEST);
1447   menu_set_current(&leveleditor_menu);
1448   arrays_init();
1449   level_load_gfx(le_current_level);
1450   loadshared();
1451   le_activate_bad_guys();
1452 }
1453
1454 void le_showhelp()
1455 {
1456   SDL_Event event;
1457   int i, done;
1458   char *text[] = {
1459                    "  - This is SuperTux's built-in level editor -",
1460                    "The level editor was made to be light, as well as, easy from",
1461                    "the start, so probabily i am just wasting my English ,-)",
1462                    "",
1463                    "At your right, you have the button bar, that allows you",
1464                    "to select tiles, both background and foregrounds, as",
1465                    "well as enemies. A-Z keys can be used as shortcuts.",
1466                    "The button bar can be used also to do level actions,",
1467                    "just as changing, save, setup and test the level. It",
1468                    "also allows you to choose between two selection cursors.",
1469                    "Scrolling the level is possible by pointing at the arrows",
1470                    "buttons or by using the right-mouse button.",
1471                    "Use the Esc key to go to the menu, in order to",
1472                    "manage subsets or just quit the level editor.",
1473                    "",
1474                    "Have fun with it and don't forget to send your levels",
1475                    "to us (using the mailing list) %-)",
1476                    "- SuperTux team"
1477                  };
1478
1479
1480   text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
1481
1482   for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1483     text_draw(&white_small_text, text[i], 5, 80+(i*12), 1, NO_UPDATE);
1484
1485   text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1486
1487   flipscreen();
1488
1489   done = 0;
1490
1491   while(done == 0)
1492     {
1493       while(SDL_PollEvent(&event))
1494         switch(event.type)
1495           {
1496           case SDL_MOUSEBUTTONDOWN:             // mouse pressed
1497           case SDL_KEYDOWN:             // key pressed
1498             done = 1;
1499             break;
1500           default:
1501             break;
1502           }
1503       SDL_Delay(50);
1504     }
1505 }