- Leveleditor improvements and fixes.
[supertux.git] / src / leveleditor.cpp
index c96e436..d7ddc42 100644 (file)
  Ricardo Cruz <rick2@aeiou.pt>
  Tobias Glaesser <tobi.web@gmx.de>                      */
 
+#include <map>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 #include <errno.h>
 #include <unistd.h>
 #include <SDL.h>
@@ -31,6 +33,7 @@
 #include "badguy.h"
 #include "scene.h"
 #include "button.h"
+#include "tile.h"
 
 /* definitions to aid development */
 #define DONE_LEVELEDITOR 1
@@ -66,7 +69,7 @@ void le_quit();
 void le_drawlevel();
 void le_drawinterface();
 void le_checkevents();
-void le_change(float x, float y, unsigned char c);
+void le_change(float x, float y, int tm, unsigned int c);
 void le_testlevel();
 void le_showhelp();
 void le_set_defaults(void);
@@ -81,7 +84,7 @@ void le_update_buttons(const char*);
 
 /* leveleditor internals */
 static string_list_type level_subsets;
-static int le_level_changed;  /* if changes, ask for saving, when quiting*/
+static bool le_level_changed;  /* if changes, ask for saving, when quiting*/
 static int pos_x, cursor_x, cursor_y, fire;
 static int le_level;
 static st_level* le_current_level;
@@ -90,8 +93,8 @@ static int le_show_grid;
 static int le_frame;
 static texture_type le_selection;
 static int done;
-static char le_current_tile;
-static int le_mouse_pressed[2];
+static unsigned int le_current_tile;
+static bool le_mouse_pressed[2];
 static button_type le_save_level_bt;
 static button_type le_test_level_bt;
 static button_type le_next_level_bt;
@@ -102,37 +105,21 @@ static button_type le_rubber_bt;
 static button_type le_select_mode_one_bt;
 static button_type le_select_mode_two_bt;
 static button_type le_settings_bt;
-static button_type le_bad_bt;
-static button_type le_bkgd_bt;
-static button_type le_fgd_bt;
-static button_panel_type le_bkgd_panel;
-static button_panel_type le_fgd_panel;
-static button_panel_type le_bad_panel;
-static menu_type leveleditor_menu;
-static menu_type subset_load_menu;
-static menu_type subset_new_menu;
-static menu_type subset_settings_menu;
-static menu_type level_settings_menu;
+static button_type le_tilegroup_bt;
+static Menu* leveleditor_menu;
+static Menu* subset_load_menu;
+static Menu* subset_new_menu;
+static Menu* subset_settings_menu;
+static Menu* level_settings_menu;
+static Menu* select_tilegroup_menu;
+static timer_type select_tilegroup_menu_effect;
+static std::map<std::string, button_panel_type > tilegroups_map;
+static std::string cur_tilegroup;
 
 static square selection;
 static int le_selection_mode;
 static SDL_Event event;
 
-void le_activate_bad_guys(void)
-{
-  int x,y;
-
-  /* Activate bad guys: */
-
-  /* as oposed to the gameloop.c func, this one doesn't remove
-  the badguys from tiles                                    */
-
-  for (y = 0; y < 15; ++y)
-    for (x = 0; x < le_current_level->width; ++x)
-      if (le_current_level->tiles[y][x] >= '0' && le_current_level->tiles[y][x] <= '9')
-        add_bad_guy(x * 32, y * 32, le_current_level->tiles[y][x] - '0');
-}
-
 void le_set_defaults()
 {
   if(le_current_level != NULL)
@@ -160,13 +147,23 @@ int leveleditor(int levelnb)
   while (SDL_PollEvent(&event))
   {}
 
-  while(YES)
+  while(true)
     {
       last_time = SDL_GetTicks();
       le_frame++;
 
       le_checkevents();
 
+      if(current_menu == select_tilegroup_menu)
+        {
+          if(timer_check(&select_tilegroup_menu_effect))
+            {
+              select_tilegroup_menu->set_pos(screen->w - 64 + timer_get_left(&select_tilegroup_menu_effect),82,-0.5,0.5);
+            }
+          else
+            select_tilegroup_menu->set_pos(screen->w - 64,82,-0.5,0.5);
+        }
+
       if(le_current_level != NULL)
         {
           /* making events results to be in order */
@@ -187,12 +184,12 @@ int leveleditor(int levelnb)
       if(show_menu)
         {
           menu_process_current();
-          if(current_menu == &leveleditor_menu)
+          if(current_menu == leveleditor_menu)
             {
-              switch (menu_check(&leveleditor_menu))
+              switch (leveleditor_menu->check())
                 {
                 case 2:
-                  show_menu = NO;
+                  show_menu = false;
                   break;
                 case 3:
                   update_subset_settings_menu();
@@ -202,22 +199,38 @@ int leveleditor(int levelnb)
                   break;
                 }
             }
-          else if(current_menu == &level_settings_menu)
+          else if(current_menu == level_settings_menu)
             {
-              switch (menu_check(&level_settings_menu))
+              switch (level_settings_menu->check())
                 {
                 case 13:
                   apply_level_settings_menu();
-                  menu_set_current(&leveleditor_menu);
+                  Menu::set_current(leveleditor_menu);
                   break;
                 default:
-                  show_menu = YES;
+                  show_menu = true;
                   break;
                 }
             }
-          else if(current_menu == &subset_load_menu)
+          else if(current_menu == select_tilegroup_menu)
             {
-              switch (i = menu_check(&subset_load_menu))
+           int it = -1;
+              switch (it = select_tilegroup_menu->check())
+                {
+                default:
+                 if(it != -1)
+                 {
+                 if(select_tilegroup_menu->item[it].kind == MN_ACTION)
+                 cur_tilegroup = select_tilegroup_menu->item[it].text;
+                 
+                  show_menu = false;
+                 }
+                  break;
+                }
+            }
+          else if(current_menu == subset_load_menu)
+            {
+              switch (i = subset_load_menu->check())
                 {
                 case 0:
                   break;
@@ -225,7 +238,7 @@ int leveleditor(int levelnb)
                   if(i != -1)
                     {
                       le_level_subset.load(level_subsets.item[i-2]);
-                      leveleditor_menu.item[3].kind = MN_GOTO;
+                      leveleditor_menu->item[3].kind = MN_GOTO;
                       le_level = 1;
                       arrays_init();
                       loadshared();
@@ -235,65 +248,65 @@ int leveleditor(int levelnb)
                           le_quit();
                           return 1;
                         }
-                     le_update_buttons(le_current_level->theme.c_str());
+                      le_update_buttons(le_current_level->theme.c_str());
                       le_set_defaults();
                       level_load_gfx(le_current_level);
-                      le_activate_bad_guys();
-                      show_menu = YES;
+                      show_menu = true;
                     }
                   break;
                 }
             }
-          else if(current_menu == &subset_new_menu)
+          else if(current_menu == subset_new_menu)
             {
-              if(subset_new_menu.item[2].input[0] == '\0')
-                subset_new_menu.item[3].kind = MN_DEACTIVE;
+              if(subset_new_menu->item[2].input[0] == '\0')
+                subset_new_menu->item[3].kind = MN_DEACTIVE;
               else
                 {
-                  subset_new_menu.item[3].kind = MN_ACTION;
+                  subset_new_menu->item[3].kind = MN_ACTION;
 
-                  switch (i = menu_check(&subset_new_menu))
+                  switch (i = subset_new_menu->check())
                     {
                     case 3:
-                     st_subset::create(subset_new_menu.item[2].input);
-                      le_level_subset.load(subset_new_menu.item[2].input);
-                      leveleditor_menu.item[3].kind = MN_GOTO;
+                      st_subset::create(subset_new_menu->item[2].input);
+                      le_level_subset.load(subset_new_menu->item[2].input);
+                      leveleditor_menu->item[3].kind = MN_GOTO;
                       le_level = 1;
                       arrays_init();
                       loadshared();
-                      le_current_level = (st_level*) malloc(sizeof(st_level));
+                      le_current_level = new st_level;
                       if(level_load(le_current_level, le_level_subset.name.c_str(), le_level) != 0)
                         {
                           le_quit();
                           return 1;
                         }
-                     le_update_buttons(le_current_level->theme.c_str());
+                      le_update_buttons(le_current_level->theme.c_str());
                       le_set_defaults();
                       level_load_gfx(le_current_level);
-                      le_activate_bad_guys();
-                      menu_item_change_input(&subset_new_menu.item[2],"");
-                      show_menu = YES;
+                      menu_item_change_input(&subset_new_menu->item[2],"");
+                      show_menu = true;
                       break;
                     }
                 }
             }
-          else if(current_menu == &subset_settings_menu)
+          else if(current_menu == subset_settings_menu)
             {
-              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  )
-                subset_settings_menu.item[5].kind = MN_DEACTIVE;
+              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  )
+                subset_settings_menu->item[5].kind = MN_DEACTIVE;
               else
-                subset_settings_menu.item[5].kind = MN_ACTION;
+                subset_settings_menu->item[5].kind = MN_ACTION;
 
-              switch (i = menu_check(&subset_settings_menu))
+              switch (i = subset_settings_menu->check())
                 {
                 case 5:
                   save_subset_settings_menu();
-                  show_menu = YES;
+                  show_menu = true;
                   break;
                 }
             }
         }
 
+      mouse_cursor->draw();
+
       if(done)
         {
           le_quit();
@@ -320,7 +333,7 @@ int leveleditor(int levelnb)
 
 void le_update_buttons(const char *theme)
 {
-  int i;
+  /*int i;
   char filename[1024];
   char pathname[1024];
   SDLKey key;
@@ -331,7 +344,7 @@ void le_update_buttons(const char *theme)
   bkgd_files =  dfiles(pathname,"bkgd-", NULL);
   string_list_sort(&bkgd_files);
 
-  le_bkgd_panel.hidden = YES;
+  le_bkgd_panel.hidden = true;
   key = SDLK_a;
   for(i = 0; i < bkgd_files.num_items; ++i)
     {
@@ -357,7 +370,7 @@ void le_update_buttons(const char *theme)
     {
       sprintf(filename,"%s/%s",pathname,fgd_files.item[i]);
       button_change_icon(&le_fgd_panel.item[i+14],filename);
-    }
+    }*/
 }
 
 int le_init()
@@ -370,21 +383,23 @@ int le_init()
   string_list_type bad_files;
   level_subsets = dsubdirs("/levels", "info");
 
-  le_show_grid = YES;
+  le_show_grid = true;
 
   /*  level_changed = NO;*/
   fire = DOWN;
   done = 0;
   le_frame = 0;        /* support for frames in some tiles, like waves and bad guys */
-  le_level_changed = NO;
+  le_level_changed = false;
   le_current_level = NULL;
 
-  le_current_tile = '.';
-  le_mouse_pressed[LEFT] = NO;
-  le_mouse_pressed[RIGHT] = NO;
+  le_current_tile = 0;
+  le_mouse_pressed[LEFT] = false;
+  le_mouse_pressed[RIGHT] = false;
 
   texture_load(&le_selection, datadir + "/images/leveleditor/select.png", USE_ALPHA);
 
+  timer_init(&select_tilegroup_menu_effect,false);
+
   /* Load buttons */
   button_load(&le_save_level_bt,"/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
   button_load(&le_next_level_bt,"/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
@@ -396,156 +411,83 @@ int le_init()
   button_load(&le_settings_bt,"/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
   button_load(&le_move_left_bt,"/images/icons/left.png","Move left",SDLK_LEFT,0,0);
   button_load(&le_move_right_bt,"/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
-  button_load(&le_fgd_bt,"/images/icons/fgd.png","Foreground tiles", SDLK_F7,screen->w-64,82);
-  button_load(&le_bkgd_bt,"/images/icons/bgd.png","Background tiles", SDLK_F8,screen->w-43,82);
-  button_load(&le_bad_bt,"/images/icons/emy.png","Enemies", SDLK_F9,screen->w-22,82);
+  button_load(&le_tilegroup_bt,"/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,82);
+
+  leveleditor_menu = new Menu();
+  subset_load_menu = new Menu();
+  subset_new_menu  = new Menu();
+  subset_settings_menu = new Menu();
+  level_settings_menu  = new Menu();
+  select_tilegroup_menu  = new Menu();
+
+  leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
+  leveleditor_menu->additem(MN_HL,"",0,0);
+  leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0);
+  leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu);
+  leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
+  leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
+  leveleditor_menu->additem(MN_HL,"",0,0);
+  leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0);
 
-  bkgd_files =  dfiles("images/themes/antarctica","bkgd-", NULL);
-  string_list_sort(&bkgd_files);
-
-  button_panel_init(&le_bkgd_panel, screen->w - 64,98, 64, 318);
-  le_bkgd_panel.hidden = YES;
-  key = SDLK_a;
-  for(i = 0; i < bkgd_files.num_items; ++i)
-    {
-      sprintf(filename,"images/themes/antarctica/%s",bkgd_files.item[i]);
-      button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i),0,0),i);
-    }
-
-  string_list_free(&bkgd_files);
-  bkgd_files = dfiles("images/shared","cloud-", NULL);
-  string_list_sort(&bkgd_files);
-
-  for(i = 0; i < bkgd_files.num_items; ++i)
-    {
-      sprintf(filename,"images/shared/%s",bkgd_files.item[i]);
-      button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i+8),0,0),i+8);
-    }
-
-  fgd_files =  dfiles("images/themes/antarctica","solid", NULL);
-  string_list_sort(&fgd_files);
-  key = SDLK_a;
-  button_panel_init(&le_fgd_panel, screen->w - 64,98, 64, 318);
-  for(i = 0; i < fgd_files.num_items; ++i)
-    {
-      sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]);
-      button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i),0,0),i);
-    }
-
-  string_list_free(&fgd_files);
-  string_list_add_item(&fgd_files,"waves-0.png");
-  string_list_add_item(&fgd_files,"water.png");
-  string_list_add_item(&fgd_files,"pole.png");
-  string_list_add_item(&fgd_files,"poletop.png");
-  string_list_add_item(&fgd_files,"flag-0.png");
-  string_list_add_item(&fgd_files,"box-empty.png");
-  string_list_add_item(&fgd_files,"mints.png");
-  string_list_add_item(&fgd_files,"distro-0.png");
-  string_list_add_item(&fgd_files,"golden-herring.png");
-  string_list_add_item(&fgd_files,"distro-0.png");
-
-  for(i = 0; i < fgd_files.num_items; ++i)
-    {
-      sprintf(filename,"images/shared/%s",fgd_files.item[i]);
-      button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+4),0,0),i+4);
-    }
-
-  string_list_free(&fgd_files);
-  fgd_files =  dfiles("images/themes/antarctica","brick", NULL);
-  string_list_sort(&fgd_files);
+  menu_reset();
+  Menu::set_current(leveleditor_menu);
+  show_menu = true;
 
-  for(i = 0; i < fgd_files.num_items; ++i)
-    {
-      sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]);
-      button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+14),0,0),i+14);
-    }
+  subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
+  subset_load_menu->additem(MN_HL, "", 0, 0);
 
-  string_list_free(&fgd_files);
-  string_list_add_item(&fgd_files,"distro-0.png");
-  string_list_add_item(&fgd_files,"distro-0.png");
-  for(i = 0; i < fgd_files.num_items; ++i)
+  for(i = 0; i < level_subsets.num_items; ++i)
     {
-      sprintf(filename,"images/shared/%s",fgd_files.item[i]);
-      button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+16),0,0),i+16);
+      subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0);
     }
-
-  le_fgd_panel.item[10].bkgd = &le_fgd_panel.item[9].icon;
-  le_fgd_panel.item[11].bkgd = &le_fgd_panel.item[9].icon;
-  le_fgd_panel.item[12].bkgd = &le_fgd_panel.item[9].icon;
-  le_fgd_panel.item[16].bkgd = &le_fgd_panel.item[14].icon;
-  le_fgd_panel.item[17].bkgd = &le_fgd_panel.item[15].icon;
-
-  string_list_init(&bad_files);
-  string_list_add_item(&bad_files,"bsod-left-0.png");
-  string_list_add_item(&bad_files,"laptop-left-0.png");
-  string_list_add_item(&bad_files,"bag-left-0.png");
-  button_panel_init(&le_bad_panel, screen->w - 64,98, 64, 318);
-  le_bad_panel.hidden = YES;
-  key = SDLK_a;
-  for(i = 0; i < bad_files.num_items; ++i)
+  subset_load_menu->additem(MN_HL,"",0,0);
+  subset_load_menu->additem(MN_BACK,"Back",0,0);
+
+  subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
+  subset_new_menu->additem(MN_HL,"",0,0);
+  subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0);
+  subset_new_menu->additem(MN_ACTION,"Create",0,0);
+  subset_new_menu->additem(MN_HL,"",0,0);
+  subset_new_menu->additem(MN_BACK,"Back",0,0);
+
+  subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
+  subset_settings_menu->additem(MN_HL,"",0,0);
+  subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0);
+  subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0);
+  subset_settings_menu->additem(MN_HL,"",0,0);
+  subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0);
+  subset_settings_menu->additem(MN_HL,"",0,0);
+  subset_settings_menu->additem(MN_BACK,"Back",0,0);
+
+  level_settings_menu->arrange_left = true;
+  level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
+  level_settings_menu->additem(MN_HL,"",0,0);
+  level_settings_menu->additem(MN_TEXTFIELD,"Name    ",0,0);
+  level_settings_menu->additem(MN_STRINGSELECT,"Theme   ",0,0);
+  level_settings_menu->additem(MN_STRINGSELECT,"Song    ",0,0);
+  level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Length ",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Time   ",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Gravity",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Red    ",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Green  ",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Blue   ",0,0);
+  level_settings_menu->additem(MN_HL,"",0,0);
+  level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0);
+
+  select_tilegroup_menu->arrange_left = true;
+  select_tilegroup_menu->additem(MN_LABEL,"Select Tilegroup",0,0);
+  select_tilegroup_menu->additem(MN_HL,"",0,0);
+  std::vector<TileGroup>* tilegroups = TileManager::tilegroups();
+  for(std::vector<TileGroup>::iterator it = tilegroups->begin(); it != tilegroups->end(); ++it )
     {
-      sprintf(filename,"images/shared/%s",bad_files.item[i]);
-      button_panel_additem(&le_bad_panel,button_create(filename, "Bad Guy",(SDLKey)((int)key+i),0,0),i);
-    }
-
-  menu_init(&leveleditor_menu);
-  menu_additem(&leveleditor_menu,menu_item_create(MN_LABEL,"Level Editor Menu",0,0));
-  menu_additem(&leveleditor_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&leveleditor_menu,menu_item_create(MN_ACTION,"Return To Level Editor",0,0));
-  menu_additem(&leveleditor_menu,menu_item_create(MN_DEACTIVE,"Level Subset Settings",0,&subset_settings_menu));
-  menu_additem(&leveleditor_menu,menu_item_create(MN_GOTO,"Load Level Subset",0,&subset_load_menu));
-  menu_additem(&leveleditor_menu,menu_item_create(MN_GOTO,"New Level Subset",0,&subset_new_menu));
-  menu_additem(&leveleditor_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&leveleditor_menu,menu_item_create(MN_ACTION,"Quit Level Editor",0,0));
-
-  menu_reset();
-  menu_set_current(&leveleditor_menu);
-  show_menu = YES;
 
-  menu_init(&subset_load_menu);
-  menu_additem(&subset_load_menu,menu_item_create(MN_LABEL,"Load Level Subset",0,0));
-  menu_additem(&subset_load_menu,menu_item_create(MN_HL,"",0,0));
-  for(i = 0; i < level_subsets.num_items; ++i)
-    {
-      menu_additem(&subset_load_menu,menu_item_create(MN_ACTION,level_subsets.item[i],0,0));
+      select_tilegroup_menu->additem(MN_ACTION,const_cast<char*>((*it).name.c_str()),0,0);
+      button_panel_init(&tilegroups_map[(*it).name], screen->w - 64,98, 64, 318);
+      for(std::vector<int>::iterator sit = (*it).tiles.begin(); sit != (*it).tiles.end(); ++sit)
+        button_panel_additem(&tilegroups_map[(*it).name],button_create(const_cast<char*>(("images/tilesets/" + TileManager::instance()->get(*sit)->filenames[0]).c_str()), const_cast<char*>((*it).name.c_str()),(SDLKey)((int)key),0,0),(*sit));
     }
-  menu_additem(&subset_load_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&subset_load_menu,menu_item_create(MN_BACK,"Back",0,0));
-
-  menu_init(&subset_new_menu);
-  menu_additem(&subset_new_menu,menu_item_create(MN_LABEL,"New Level Subset",0,0));
-  menu_additem(&subset_new_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&subset_new_menu,menu_item_create(MN_TEXTFIELD,"Enter Name",0,0));
-  menu_additem(&subset_new_menu,menu_item_create(MN_ACTION,"Create",0,0));
-  menu_additem(&subset_new_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&subset_new_menu,menu_item_create(MN_BACK,"Back",0,0));
-
-  menu_init(&subset_settings_menu);
-  menu_additem(&subset_settings_menu,menu_item_create(MN_LABEL,"Level Subset Settings",0,0));
-  menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&subset_settings_menu,menu_item_create(MN_TEXTFIELD,"Title",0,0));
-  menu_additem(&subset_settings_menu,menu_item_create(MN_TEXTFIELD,"Description",0,0));
-  menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&subset_settings_menu,menu_item_create(MN_ACTION,"Save Changes",0,0));
-  menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&subset_settings_menu,menu_item_create(MN_BACK,"Back",0,0));
-
-  menu_init(&level_settings_menu);
-  level_settings_menu.arrange_left = YES;
-  menu_additem(&level_settings_menu,menu_item_create(MN_LABEL,"Level Settings",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_TEXTFIELD,"Name    ",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Theme   ",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Song    ",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Bg-Image",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Length ",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Time   ",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Gravity",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Red    ",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Green  ",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Blue   ",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_HL,"",0,0));
-  menu_additem(&level_settings_menu,menu_item_create(MN_ACTION,"Apply Changes",0,0));
+  select_tilegroup_menu->additem(MN_HL,"",0,0);
 
   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
 
@@ -557,100 +499,79 @@ void update_level_settings_menu()
   char str[80];
   int i;
 
-  menu_item_change_input(&level_settings_menu.item[2], le_current_level->name.c_str());
+  menu_item_change_input(&level_settings_menu->item[2], le_current_level->name.c_str());
   sprintf(str,"%d",le_current_level->width);
 
-  string_list_copy(level_settings_menu.item[3].list, dsubdirs("images/themes", "solid0.png"));
-  string_list_copy(level_settings_menu.item[4].list, dfiles("music/",NULL, "-fast"));
-  string_list_copy(level_settings_menu.item[5].list, dfiles("images/background",NULL, NULL));
-  string_list_add_item(level_settings_menu.item[5].list,"");
-  if((i = string_list_find(level_settings_menu.item[3].list,le_current_level->theme.c_str())) != -1)
-    level_settings_menu.item[3].list->active_item = i;
-  if((i = string_list_find(level_settings_menu.item[4].list,le_current_level->song_title.c_str())) != -1)
-    level_settings_menu.item[4].list->active_item = i;
-  if((i = string_list_find(level_settings_menu.item[5].list,le_current_level->bkgd_image.c_str())) != -1)
-    level_settings_menu.item[5].list->active_item = i;
-
-  menu_item_change_input(&level_settings_menu.item[6], str);
+  string_list_copy(level_settings_menu->item[3].list, dsubdirs("images/themes", "solid0.png"));
+  string_list_copy(level_settings_menu->item[4].list, dfiles("music/",NULL, "-fast"));
+  string_list_copy(level_settings_menu->item[5].list, dfiles("images/background",NULL, NULL));
+  string_list_add_item(level_settings_menu->item[5].list,"");
+  if((i = string_list_find(level_settings_menu->item[3].list,le_current_level->theme.c_str())) != -1)
+    level_settings_menu->item[3].list->active_item = i;
+  if((i = string_list_find(level_settings_menu->item[4].list,le_current_level->song_title.c_str())) != -1)
+    level_settings_menu->item[4].list->active_item = i;
+  if((i = string_list_find(level_settings_menu->item[5].list,le_current_level->bkgd_image.c_str())) != -1)
+    level_settings_menu->item[5].list->active_item = i;
+
+  menu_item_change_input(&level_settings_menu->item[6], str);
   sprintf(str,"%d",le_current_level->time_left);
-  menu_item_change_input(&level_settings_menu.item[7], str);
+  menu_item_change_input(&level_settings_menu->item[7], str);
   sprintf(str,"%2.0f",le_current_level->gravity);
-  menu_item_change_input(&level_settings_menu.item[8], str);
+  menu_item_change_input(&level_settings_menu->item[8], str);
   sprintf(str,"%d",le_current_level->bkgd_red);
-  menu_item_change_input(&level_settings_menu.item[9], str);
+  menu_item_change_input(&level_settings_menu->item[9], str);
   sprintf(str,"%d",le_current_level->bkgd_green);
-  menu_item_change_input(&level_settings_menu.item[10], str);
+  menu_item_change_input(&level_settings_menu->item[10], str);
   sprintf(str,"%d",le_current_level->bkgd_blue);
-  menu_item_change_input(&level_settings_menu.item[11], str);
+  menu_item_change_input(&level_settings_menu->item[11], str);
 }
 
 void update_subset_settings_menu()
 {
-  menu_item_change_input(&subset_settings_menu.item[2], le_level_subset.title.c_str());
-  menu_item_change_input(&subset_settings_menu.item[3], le_level_subset.description.c_str());
+  menu_item_change_input(&subset_settings_menu->item[2], le_level_subset.title.c_str());
+  menu_item_change_input(&subset_settings_menu->item[3], le_level_subset.description.c_str());
 }
 
 void apply_level_settings_menu()
 {
-  int i,y,j;
-  i = NO;
+  int i;
+  i = false;
 
-  le_current_level->name = level_settings_menu.item[2].input;
+  le_current_level->name = level_settings_menu->item[2].input;
 
-  if(le_current_level->bkgd_image.compare(string_list_active(level_settings_menu.item[5].list)) != 0)
+  if(le_current_level->bkgd_image.compare(string_list_active(level_settings_menu->item[5].list)) != 0)
     {
-      le_current_level->bkgd_image = string_list_active(level_settings_menu.item[5].list);
-      i = YES;
+      le_current_level->bkgd_image = string_list_active(level_settings_menu->item[5].list);
+      i = true;
     }
 
-  if(le_current_level->theme.compare(string_list_active(level_settings_menu.item[3].list)) != 0)
+  if(le_current_level->theme.compare(string_list_active(level_settings_menu->item[3].list)) != 0)
     {
-      le_current_level->theme = string_list_active(level_settings_menu.item[3].list);
+      le_current_level->theme = string_list_active(level_settings_menu->item[3].list);
       le_update_buttons(le_current_level->theme.c_str());
-      i = YES;
+      i = true;
     }
 
-  if(i == YES)
+  if(i)
     {
       level_free_gfx();
       level_load_gfx(le_current_level);
     }
 
-  le_current_level->song_title = string_list_active(level_settings_menu.item[4].list);
+  le_current_level->song_title = string_list_active(level_settings_menu->item[4].list);
 
-  i = le_current_level->width;
-  le_current_level->width = atoi(level_settings_menu.item[6].input);
-  if(le_current_level->width < i)
-    {
-      if(le_current_level->width < 21)
-        le_current_level->width = 21;
-      for(y = 0; y < 15; ++y)
-        {
-          le_current_level->tiles[y] = (unsigned int*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned int));
-          le_current_level->tiles[y][le_current_level->width] = (unsigned int) '\0';
-        }
-    }
-  else if(le_current_level->width > i)
-    {
-      for(y = 0; y < 15; ++y)
-        {
-          le_current_level->tiles[y] = (unsigned int*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned int));
-          for(j = 0; j < le_current_level->width - i; ++j)
-            le_current_level->tiles[y][i+j] = (unsigned int) '.';
-          le_current_level->tiles[y][le_current_level->width] = (unsigned int) '\0';
-        }
-    }
-  le_current_level->time_left = atoi(level_settings_menu.item[7].input);
-  le_current_level->gravity = atof(level_settings_menu.item[8].input);
-  le_current_level->bkgd_red = atoi(level_settings_menu.item[9].input);
-  le_current_level->bkgd_green = atoi(level_settings_menu.item[10].input);
-  le_current_level->bkgd_blue = atoi(level_settings_menu.item[11].input);
+  level_change_size(le_current_level, atoi(level_settings_menu->item[6].input));
+  le_current_level->time_left = atoi(level_settings_menu->item[7].input);
+  le_current_level->gravity = atof(level_settings_menu->item[8].input);
+  le_current_level->bkgd_red = atoi(level_settings_menu->item[9].input);
+  le_current_level->bkgd_green = atoi(level_settings_menu->item[10].input);
+  le_current_level->bkgd_blue = atoi(level_settings_menu->item[11].input);
 }
 
 void save_subset_settings_menu()
 {
-  le_level_subset.title = subset_settings_menu.item[2].input;
-  le_level_subset.description = subset_settings_menu.item[3].input;
+  le_level_subset.title = subset_settings_menu->item[2].input;
+  le_level_subset.description = subset_settings_menu->item[3].input;
   le_level_subset.save();
 }
 
@@ -675,27 +596,23 @@ void le_goto_level(int levelnb)
 
   level_free_gfx();
   level_load_gfx(le_current_level);
-
-  le_activate_bad_guys();
 }
 
 void le_quit(void)
 {
-  /*if(level_changed == YES)
+  /*if(level_changed == true)
     if(askforsaving() == CANCEL)
       return;*/ //FIXME
 
   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
 
   texture_free(&le_selection);
-  menu_free(&leveleditor_menu);
-  menu_free(&subset_load_menu);
-  menu_free(&subset_new_menu);
-  menu_free(&subset_settings_menu);
-  menu_free(&level_settings_menu);
-  button_panel_free(&le_bkgd_panel);
-  button_panel_free(&le_fgd_panel);
-  button_panel_free(&le_bad_panel);
+  delete leveleditor_menu;
+  delete subset_load_menu;
+  delete subset_new_menu;
+  delete subset_settings_menu;
+  delete level_settings_menu;
+  delete select_tilegroup_menu;
   button_free(&le_save_level_bt);
   button_free(&le_test_level_bt);
   button_free(&le_next_level_bt);
@@ -706,9 +623,7 @@ void le_quit(void)
   button_free(&le_select_mode_one_bt);
   button_free(&le_select_mode_two_bt);
   button_free(&le_settings_bt);
-  button_free(&le_bad_bt);
-  button_free(&le_bkgd_bt);
-  button_free(&le_fgd_bt);
+  button_free(&le_tilegroup_bt);
 
   if(le_current_level != NULL)
     {
@@ -737,7 +652,7 @@ void le_drawinterface()
     }
 
   if(le_selection_mode == CURSOR)
-    texture_draw(&le_selection, cursor_x - pos_x, cursor_y, NO_UPDATE);
+    texture_draw(&le_selection, cursor_x - pos_x, cursor_y);
   else if(le_selection_mode == SQUARE)
     {
       int w, h;
@@ -758,24 +673,24 @@ void le_drawinterface()
   switch(le_current_tile)
     {
     case 'B':
-      texture_draw(&img_mints, 19 * 32, 14 * 32, NO_UPDATE);
+      texture_draw(&img_mints, 19 * 32, 14 * 32);
       break;
     case '!':
-      texture_draw(&img_golden_herring,19 * 32, 14 * 32, NO_UPDATE);
+      texture_draw(&img_golden_herring,19 * 32, 14 * 32);
       break;
     case 'x':
     case 'y':
     case 'A':
-      texture_draw(&img_distro[(le_frame / 5) % 4], 19 * 32, 14 * 32, NO_UPDATE);
+      texture_draw(&img_distro[(le_frame / 5) % 4], 19 * 32, 14 * 32);
       break;
     case '0':
-      texture_draw(&img_bsod_left[(le_frame / 5) % 4],19 * 32, 14 * 32, NO_UPDATE);
+      texture_draw(&img_bsod_left[(le_frame / 5) % 4],19 * 32, 14 * 32);
       break;
     case '1':
-      texture_draw(&img_laptop_left[(le_frame / 5) % 3],19 * 32, 14 * 32, NO_UPDATE);
+      texture_draw(&img_laptop_left[(le_frame / 5) % 3],19 * 32, 14 * 32);
       break;
     case '2':
-      texture_draw(&img_money_left[0],19 * 32, 14 * 32, NO_UPDATE);
+      texture_draw(&img_money_left[0],19 * 32, 14 * 32);
       break;
     default:
       break;
@@ -793,38 +708,34 @@ void le_drawinterface()
       button_draw(&le_settings_bt);
       button_draw(&le_move_right_bt);
       button_draw(&le_move_left_bt);
-      button_draw(&le_bad_bt);
-      button_draw(&le_bkgd_bt);
-      button_draw(&le_fgd_bt);
-      button_panel_draw(&le_bkgd_panel);
-      button_panel_draw(&le_fgd_panel);
-      button_panel_draw(&le_bad_panel);
+      button_draw(&le_tilegroup_bt);
+      button_panel_draw(&tilegroups_map[cur_tilegroup]);
 
       sprintf(str, "%d/%d", le_level,le_level_subset.levels);
-      text_drawf(&white_text, str, -8, 16, A_RIGHT, A_NONE, 1, NO_UPDATE);
+      text_drawf(&white_text, str, -8, 16, A_RIGHT, A_TOP, 1);
 
-      text_draw(&white_small_text, "F1 for Help", 10, 430, 1, NO_UPDATE);
+      text_draw(&white_small_text, "F1 for Help", 10, 430, 1);
     }
   else
     {
-      if(show_menu == NO)
-        text_draw(&white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1, NO_UPDATE);
+      if(show_menu == false)
+        text_draw(&white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
       else
-        text_draw(&white_small_text, "No Level Subset loaded", 10, 430, 1, NO_UPDATE);
+        text_draw(&white_small_text, "No Level Subset loaded", 10, 430, 1);
     }
 
 }
 
 void le_drawlevel()
 {
-  int y,x,i,s;
+  unsigned int y,x,i,s;
 
   /* Draw the real background */
   if(le_current_level->bkgd_image[0] != '\0')
     {
       s = pos_x / 30;
-      texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s - 32, img_bkgd.h, NO_UPDATE);
-      texture_draw_part(&img_bkgd,0,0,screen->w - s - 32 ,0,s,img_bkgd.h, NO_UPDATE);
+      texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s - 32, img_bkgd.h);
+      texture_draw_part(&img_bkgd,0,0,screen->w - s - 32 ,0,s,img_bkgd.h);
     }
   else
     {
@@ -836,22 +747,22 @@ void le_drawlevel()
   for (y = 0; y < 15; ++y)
     for (x = 0; x < 20; ++x)
       {
-        drawshape(x * 32 - ((int)pos_x % 32), y * 32, le_current_level->tiles[y][x + (int)(pos_x / 32)]);
+        drawshape(32*x - fmodf(pos_x, 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)]);
 
         /* draw whats inside stuff when cursor is selecting those */
         /* (draw them all the time - is this the right behaviour?) */
-        switch(le_current_level->tiles[y][x + (int)(pos_x/32)])
+        switch(le_current_level->ia_tiles[y][x + (int)(pos_x/32)])
           {
           case 'B':
-            texture_draw(&img_mints, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
+            texture_draw(&img_mints, x * 32 - ((int)pos_x % 32), y*32);
             break;
           case '!':
-            texture_draw(&img_golden_herring, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
+            texture_draw(&img_golden_herring, x * 32 - ((int)pos_x % 32), y*32);
             break;
           case 'x':
           case 'y':
           case 'A':
-            texture_draw(&img_distro[(frame / 5) % 4], x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
+            texture_draw(&img_distro[(global_frame_counter / 5) % 4], x * 32 - ((int)pos_x % 32), y*32);
             break;
           default:
             break;
@@ -859,23 +770,21 @@ void le_drawlevel()
       }
 
   /* Draw the Bad guys: */
-  for (i = 0; i < num_bad_guys; ++i)
+  for (i = 0; i < bad_guys.size(); ++i)
     {
-      if(bad_guys[i].base.alive == NO)
-        continue;
       /* to support frames: img_bsod_left[(frame / 5) % 4] */
       if(bad_guys[i].kind == BAD_BSOD)
-        texture_draw(&img_bsod_left[(le_frame / 5) % 4], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
+        texture_draw(&img_bsod_left[(le_frame / 5) % 4], bad_guys[i].base.x - pos_x, bad_guys[i].base.y);
       else if(bad_guys[i].kind == BAD_LAPTOP)
-        texture_draw(&img_laptop_left[(le_frame / 5) % 3], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
+        texture_draw(&img_laptop_left[(le_frame / 5) % 3], bad_guys[i].base.x - pos_x, bad_guys[i].base.y);
       else if (bad_guys[i].kind == BAD_MONEY)
-        texture_draw(&img_money_left[(le_frame / 5) % 2], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
+        texture_draw(&img_money_left[(le_frame / 5) % 2], bad_guys[i].base.x - pos_x, bad_guys[i].base.y);
     }
 
 
   /* Draw the player: */
   /* for now, the position is fixed at (0, 240) */
-  texture_draw(&tux_right[(frame / 5) % 3], 0 - pos_x, 240, NO_UPDATE);
+  texture_draw(&tux_right[(global_frame_counter / 5) % 3], 0 - pos_x, 240);
 }
 
 void le_checkevents()
@@ -889,22 +798,25 @@ void le_checkevents()
 
   while(SDL_PollEvent(&event))
     {
+      if(show_menu)
+        menu_event(event);
+      else
+        mouse_cursor->set_state(MC_NORMAL);
+
       /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
       if(event.type == SDL_KEYDOWN || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > 0 && event.motion.x < screen->w - 64 &&
                                        event.motion.y > 0 && event.motion.y < screen->h)))
         {
-
           switch(event.type)
             {
             case SDL_KEYDOWN:  // key pressed
               key = event.key.keysym.sym;
               if(show_menu)
                 {
-                  menu_event(&event.key.keysym);
                   if(key == SDLK_ESCAPE)
                     {
-                      show_menu = NO;
-                      menu_set_current(&leveleditor_menu);
+                      show_menu = false;
+                      Menu::set_current(leveleditor_menu);
                     }
                   break;
                 }
@@ -912,9 +824,9 @@ void le_checkevents()
                 {
                 case SDLK_ESCAPE:
                   if(!show_menu)
-                    show_menu = YES;
+                    show_menu = true;
                   else
-                    show_menu = NO;
+                    show_menu = false;
                   break;
                 case SDLK_LEFT:
                   if(fire == DOWN)
@@ -988,7 +900,7 @@ void le_checkevents()
             case SDL_MOUSEBUTTONDOWN:
               if(event.button.button == SDL_BUTTON_LEFT)
                 {
-                  le_mouse_pressed[LEFT] = YES;
+                  le_mouse_pressed[LEFT] = true;
 
                   selection.x1 = event.motion.x + pos_x;
                   selection.y1 = event.motion.y;
@@ -996,13 +908,13 @@ void le_checkevents()
                   selection.y2 = event.motion.y;
                 }
               else if(event.button.button == SDL_BUTTON_RIGHT)
-                le_mouse_pressed[RIGHT] = YES;
+                le_mouse_pressed[RIGHT] = true;
               break;
             case SDL_MOUSEBUTTONUP:
               if(event.button.button == SDL_BUTTON_LEFT)
-                le_mouse_pressed[LEFT] = NO;
+                le_mouse_pressed[LEFT] = false;
               else if(event.button.button == SDL_BUTTON_RIGHT)
-                le_mouse_pressed[RIGHT] = NO;
+                le_mouse_pressed[RIGHT] = false;
               break;
             case SDL_MOUSEMOTION:
               if(!show_menu)
@@ -1013,13 +925,13 @@ void le_checkevents()
                   cursor_x = ((int)(pos_x + x) / 32) * 32;
                   cursor_y = ((int) y / 32) * 32;
 
-                  if(le_mouse_pressed[LEFT] == YES)
+                  if(le_mouse_pressed[LEFT])
                     {
                       selection.x2 = x + pos_x;
                       selection.y2 = y;
                     }
 
-                  if(le_mouse_pressed[RIGHT] == YES)
+                  if(le_mouse_pressed[RIGHT])
                     {
                       pos_x += -1 * event.motion.xrel;
                     }
@@ -1038,20 +950,20 @@ void le_checkevents()
           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 &&
               event.motion.y > 0 && event.motion.y < screen->h)))
             {
-              le_mouse_pressed[LEFT] = NO;
-              le_mouse_pressed[RIGHT] = NO;
+              le_mouse_pressed[LEFT] = false;
+              le_mouse_pressed[RIGHT] = false;
 
-              if(show_menu == NO)
+              if(show_menu == false)
                 {
                   /* Check for button events */
                   button_event(&le_test_level_bt,&event);
-                  if(button_get_state(&le_test_level_bt) == BN_CLICKED)
+                  if(button_get_state(&le_test_level_bt) == BUTTON_CLICKED)
                     le_testlevel();
                   button_event(&le_save_level_bt,&event);
-                  if(button_get_state(&le_save_level_bt) == BN_CLICKED)
+                  if(button_get_state(&le_save_level_bt) == BUTTON_CLICKED)
                     level_save(le_current_level,le_level_subset.name.c_str(),le_level);
                   button_event(&le_next_level_bt,&event);
-                  if(button_get_state(&le_next_level_bt) == BN_CLICKED)
+                  if(button_get_state(&le_next_level_bt) == BUTTON_CLICKED)
                     {
                       if(le_level < le_level_subset.levels)
                         {
@@ -1063,9 +975,9 @@ void le_checkevents()
                           char str[1024];
                           int d = 0;
                           sprintf(str,"Level %d doesn't exist.",le_level+1);
-                          text_drawf(&white_text,str,0,-18,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE);
-                          text_drawf(&white_text,"Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE);
-                          text_drawf(&red_text,"(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE);
+                          text_drawf(&white_text,str,0,-18,A_HMIDDLE,A_VMIDDLE,2);
+                          text_drawf(&white_text,"Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2);
+                          text_drawf(&red_text,"(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2);
                           flipscreen();
                           while(d == 0)
                             {
@@ -1084,8 +996,8 @@ void le_checkevents()
                                         break;
                                       case SDLK_n:
                                         d = 1;
-                                       break;
-                                     default:
+                                        break;
+                                      default:
                                         break;
                                       }
                                     break;
@@ -1097,61 +1009,47 @@ void le_checkevents()
                         }
                     }
                   button_event(&le_previous_level_bt,&event);
-                  if(button_get_state(&le_previous_level_bt) == BN_CLICKED)
+                  if(button_get_state(&le_previous_level_bt) == BUTTON_CLICKED)
                     {
                       if(le_level > 1)
                         le_goto_level(--le_level);
                     }
                   button_event(&le_rubber_bt,&event);
-                  if(button_get_state(&le_rubber_bt) == BN_CLICKED)
-                    le_current_tile = '.';
+                  if(button_get_state(&le_rubber_bt) == BUTTON_CLICKED)
+                    le_current_tile = 0;
                   button_event(&le_select_mode_one_bt,&event);
-                  if(button_get_state(&le_select_mode_one_bt) == BN_CLICKED)
+                  if(button_get_state(&le_select_mode_one_bt) == BUTTON_CLICKED)
                     le_selection_mode = CURSOR;
                   button_event(&le_select_mode_two_bt,&event);
-                  if(button_get_state(&le_select_mode_two_bt) == BN_CLICKED)
+                  if(button_get_state(&le_select_mode_two_bt) == BUTTON_CLICKED)
                     le_selection_mode = SQUARE;
 
-                  button_event(&le_bad_bt,&event);
-                  if(button_get_state(&le_bad_bt) == BN_CLICKED)
+                  button_event(&le_tilegroup_bt,&event);
+                  if(button_get_state(&le_tilegroup_bt) == BUTTON_CLICKED)
                     {
-                      le_bad_panel.hidden = NO;
-                      le_fgd_panel.hidden = YES;
-                      le_bkgd_panel.hidden = YES;
+                      Menu::set_current(select_tilegroup_menu);
+                      timer_start(&select_tilegroup_menu_effect,200);
+                      select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
+                      show_menu = true;
                     }
 
-                  button_event(&le_fgd_bt,&event);
-                  if(button_get_state(&le_fgd_bt) == BN_CLICKED)
-                    {
-                      le_bad_panel.hidden = YES;
-                      le_fgd_panel.hidden = NO;
-                      le_bkgd_panel.hidden = YES;
-                    }
-                  button_event(&le_bkgd_bt,&event);
-                  if(button_get_state(&le_bkgd_bt) == BN_CLICKED)
-                    {
-                      le_bad_panel.hidden = YES;
-                      le_fgd_panel.hidden = YES;
-                      le_bkgd_panel.hidden = NO;
-                    }
                   button_event(&le_settings_bt,&event);
-                  if(button_get_state(&le_settings_bt) == BN_CLICKED)
+                  if(button_get_state(&le_settings_bt) == BUTTON_CLICKED)
                     {
-                      if(show_menu == NO)
-                        {
-                          update_level_settings_menu();
-                          menu_set_current(&level_settings_menu);
-                          show_menu = YES;
-                        }
-                      else
-                        {
-                          menu_set_current(&leveleditor_menu);
-                          show_menu = NO;
-                        }
+                      update_level_settings_menu();
+                      Menu::set_current(level_settings_menu);
+                      show_menu = true;
                     }
-                  if((pbutton = button_panel_event(&le_bkgd_panel,&event)) != NULL)
+                 if((pbutton = button_panel_event(&tilegroups_map[cur_tilegroup],&event)) != NULL)
+                 {
+                   if(button_get_state(pbutton) == BUTTON_CLICKED)
+                     {
+                     le_current_tile = pbutton->tag;
+                     }
+                 }
+                  /*if((pbutton = button_panel_event(&le_bkgd_panel,&event)) != NULL)
                     {
-                      if(button_get_state(pbutton) == BN_CLICKED)
+                      if(button_get_state(pbutton) == BUTTON_CLICKED)
                         {
                           char c = '\0';
                           if(pbutton->tag >= 0 && pbutton->tag <= 3)
@@ -1165,111 +1063,52 @@ void le_checkevents()
                           if(c != '\0')
                             le_current_tile = c;
                         }
-                    }
-                  if((pbutton = button_panel_event(&le_fgd_panel,&event)) != NULL)
-                    {
-                      if(button_get_state(pbutton) == BN_CLICKED)
-                        {
-                          char c = '\0';
-                          if(pbutton->tag == 0)
-                            c = '#' ;
-                          else if(pbutton->tag == 1)
-                            c = '[';
-                          else if(pbutton->tag == 2)
-                            c = '=';
-                          else if(pbutton->tag == 3)
-                            c = ']';
-                          else if(pbutton->tag == 4)
-                            c = '^';
-                          else if(pbutton->tag == 5)
-                            c = '&';
-                          else if(pbutton->tag == 6)
-                            c = '|';
-                          else if(pbutton->tag == 7)
-                            c = '*';
-                          else if(pbutton->tag == 8)
-                            c = '\\';
-                          else if(pbutton->tag == 9)
-                            c = 'a';
-                          else if(pbutton->tag == 10)
-                            c = 'B';
-                          else if(pbutton->tag == 11)
-                            c = 'A';
-                          else if(pbutton->tag == 12)
-                            c = '!';
-                          else if(pbutton->tag == 13)
-                            c = '$';
-                          else if(pbutton->tag == 14)
-                            c = 'X';
-                          else if(pbutton->tag == 15)
-                            c = 'Y';
-                          else if(pbutton->tag == 16)
-                            c = 'x';
-                          else if(pbutton->tag == 17)
-                            c = 'y';
-                          if(c != '\0')
-                            le_current_tile = c;
-                        }
-                    }
-                  if((pbutton = button_panel_event(&le_bad_panel,&event)) != NULL)
-                    {
-                      if(button_get_state(pbutton) == BN_CLICKED)
-                        {
-                          char c = '\0';
-                          if(pbutton->tag >= 0 && pbutton->tag <= 2)
-                            c = '0' + pbutton->tag;
-                          if(c != '\0')
-                            le_current_tile = c;
-                        }
-                    }
+                    }*/
                 }
               else
                 {
                   button_event(&le_settings_bt,&event);
-                  if(button_get_state(&le_settings_bt) == BN_CLICKED)
+                  if(button_get_state(&le_settings_bt) == BUTTON_CLICKED)
                     {
-                      if(show_menu == NO)
-                        {
-                          update_level_settings_menu();
-                          menu_set_current(&level_settings_menu);
-                          show_menu = YES;
-                        }
-                      else
-                        {
-                          menu_set_current(&leveleditor_menu);
-                          show_menu = NO;
-                        }
+                      Menu::set_current(leveleditor_menu);
+                      show_menu = false;
+                    }
+                  button_event(&le_tilegroup_bt,&event);
+                  if(button_get_state(&le_tilegroup_bt) == BUTTON_CLICKED)
+                    {
+                      Menu::set_current(leveleditor_menu);
+                      show_menu = false;
                     }
                 }
             }
-          if(show_menu == NO)
+          if(show_menu == false)
             {
               button_event(&le_move_left_bt,&event);
               button_event(&le_move_right_bt,&event);
 
               if(le_mouse_pressed[LEFT])
                 {
-                  le_change(cursor_x, cursor_y, le_current_tile);
+                  le_change(cursor_x, cursor_y, TM_IA, le_current_tile);
                 }
             }
         }
     }
-  if(show_menu == NO)
+  if(show_menu == false)
     {
-      if(button_get_state(&le_move_left_bt) == BN_PRESSED)
+      if(button_get_state(&le_move_left_bt) == BUTTON_PRESSED)
         {
           pos_x -= 192;
         }
-      else if(button_get_state(&le_move_left_bt) == BN_HOVER)
+      else if(button_get_state(&le_move_left_bt) == BUTTON_HOVER)
         {
           pos_x -= 96;
         }
 
-      if(button_get_state(&le_move_right_bt) == BN_PRESSED)
+      if(button_get_state(&le_move_right_bt) == BUTTON_PRESSED)
         {
           pos_x += 192;
         }
-      else if(button_get_state(&le_move_right_bt) == BN_HOVER)
+      else if(button_get_state(&le_move_right_bt) == BUTTON_HOVER)
         {
           pos_x += 96;
         }
@@ -1310,28 +1149,28 @@ void le_highlight_selection()
   fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
 }
 
-void le_change(float x, float y, unsigned char c)
+void le_change(float x, float y, int tm, unsigned int c)
 {
   if(le_current_level != NULL)
     {
-      int xx,yy,i;
+      int xx,yy;
       int x1, x2, y1, y2;
+      unsigned int i;
 
-      /*  level_changed = YES; */
+      /*  level_changed = true; */
 
       switch(le_selection_mode)
         {
         case CURSOR:
-          level_change(le_current_level,x,y,c);
+          level_change(le_current_level,x,y,tm,c);
 
           yy = ((int)y / 32);
           xx = ((int)x / 32);
 
           /* if there is a bad guy over there, remove it */
-          for(i = 0; i < num_bad_guys; ++i)
-            if (bad_guys[i].base.alive)
-              if(xx == bad_guys[i].base.x/32 && yy == bad_guys[i].base.y/32)
-                bad_guys[i].base.alive = NO;
+          for(i = 0; i < bad_guys.size(); ++i)
+            if(xx == bad_guys[i].base.x/32 && yy == bad_guys[i].base.y/32)
+              bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&bad_guys[i]));
 
           if(c == '0')  /* if it's a bad guy */
             add_bad_guy(xx*32, yy*32, BAD_BSOD);
@@ -1369,16 +1208,15 @@ void le_change(float x, float y, unsigned char c)
           y2 /= 32;
 
           /* if there is a bad guy over there, remove it */
-          for(i = 0; i < num_bad_guys; ++i)
-            if(bad_guys[i].base.alive)
-              if(bad_guys[i].base.x/32 >= x1 && bad_guys[i].base.x/32 <= x2
-                  && bad_guys[i].base.y/32 >= y1 && bad_guys[i].base.y/32 <= y2)
-                bad_guys[i].base.alive = NO;
+          for(i = 0; i < bad_guys.size(); ++i)
+            if(bad_guys[i].base.x/32 >= x1 && bad_guys[i].base.x/32 <= x2
+                && bad_guys[i].base.y/32 >= y1 && bad_guys[i].base.y/32 <= y2)
+              bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&bad_guys[i]));
 
           for(xx = x1; xx <= x2; xx++)
             for(yy = y1; yy <= y2; yy++)
               {
-                level_change(le_current_level, xx*32, yy*32, c);
+                level_change(le_current_level, xx*32, yy*32, tm, c);
 
                 if(c == '0')  // if it's a bad guy
                   add_bad_guy(xx*32, yy*32, BAD_BSOD);
@@ -1398,11 +1236,10 @@ void le_testlevel()
 {
   level_save(le_current_level,"test",le_level);
   gameloop("test",le_level, ST_GL_TEST);
-  menu_set_current(&leveleditor_menu);
+  Menu::set_current(leveleditor_menu);
   arrays_init();
   level_load_gfx(le_current_level);
   loadshared();
-  le_activate_bad_guys();
 }
 
 void le_showhelp()
@@ -1431,22 +1268,22 @@ void le_showhelp()
                    "settings of your level, including how long it is or what music it will",
                    "play. When you are ready to give your level a test, click on the little",
                    "running Tux. If you like the changes you have made to your level,",
-                                  "press the red save key to keep them.",
+                   "press the red save key to keep them.",
                    "To change which level in your subset you are editing, press the white",
                    "up and down arrow keys at the top of the button box.",
-                                  "",
+                   "",
                    "Have fun making levels! If you make some good ones, send them to us on",
-                                  "the SuperTux mailing list!",
+                   "the SuperTux mailing list!",
                    "- SuperTux team"
                  };
 
 
-  text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
+  text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
 
   for(i = 0; i < sizeof(text)/sizeof(char *); i++)
-    text_draw(&white_small_text, text[i], 5, 80+(i*12), 1, NO_UPDATE);
+    text_draw(&white_small_text, text[i], 5, 80+(i*12), 1);
 
-  text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
+  text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
 
   flipscreen();