- converted text_type into a class
[supertux.git] / src / leveleditor.cpp
index 7cb6be6..e18011d 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>
 #include <SDL_image.h>
 #include "leveleditor.h"
 
+#include "world.h"
 #include "screen.h"
 #include "defines.h"
 #include "globals.h"
 #include "setup.h"
 #include "menu.h"
 #include "level.h"
+#include "gameloop.h"
 #include "badguy.h"
 #include "scene.h"
 #include "button.h"
+#include "tile.h"
+#include "resources.h"
 
 /* definitions to aid development */
 #define DONE_LEVELEDITOR 1
 #define SELECT_W 2 // size of the selections lines
 #define SELECT_CLR 0, 255, 0, 255  // lines color (R, G, B, A)
 
-/* gameloop funcs declerations */
-
-void loadshared(void);
-void unloadshared(void);
-
 /* own declerations */
 /* crutial ones (main loop) */
 int le_init();
@@ -77,46 +78,48 @@ void le_highlight_selection();
 void apply_level_settings_menu();
 void update_subset_settings_menu();
 void save_subset_settings_menu();
-void le_update_buttons(const char*);
 
 /* leveleditor internals */
 static string_list_type level_subsets;
 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;
+static Level* le_current_level;
+static World le_world;
 static st_subset le_level_subset;
 static int le_show_grid;
 static int le_frame;
-static texture_type le_selection;
+static Surface* le_selection;
 static int done;
 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;
-static button_type le_previous_level_bt;
-static button_type le_move_right_bt;
-static button_type le_move_left_bt;
-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 Button* le_save_level_bt;
+static Button* le_exit_bt;
+static Button* le_test_level_bt;
+static Button* le_next_level_bt;
+static Button* le_previous_level_bt;
+static Button* le_move_right_bt;
+static Button* le_move_left_bt;
+static Button* le_rubber_bt;
+static Button* le_select_mode_one_bt;
+static Button* le_select_mode_two_bt;
+static Button* le_settings_bt;
+static Button* le_tilegroup_bt;
+static ButtonPanel* le_tilemap_panel;
 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 select_tilegroup_menu_effect;
+static std::map<std::string, ButtonPanel* > tilegroups_map;
+static std::string cur_tilegroup;
 
 static square selection;
 static int le_selection_mode;
 static SDL_Event event;
+TileMapType active_tm;
 
 void le_set_defaults()
 {
@@ -152,6 +155,17 @@ int leveleditor(int levelnb)
 
       le_checkevents();
 
+      if(current_menu == select_tilegroup_menu)
+        {
+          if(select_tilegroup_menu_effect.check())
+            {
+              select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
+                                             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 */
@@ -191,7 +205,7 @@ int leveleditor(int levelnb)
             {
               switch (level_settings_menu->check())
                 {
-                case 13:
+                case 17:
                   apply_level_settings_menu();
                   Menu::set_current(leveleditor_menu);
                   break;
@@ -200,6 +214,22 @@ int leveleditor(int levelnb)
                   break;
                 }
             }
+          else if(current_menu == select_tilegroup_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())
@@ -212,17 +242,16 @@ int leveleditor(int levelnb)
                       le_level_subset.load(level_subsets.item[i-2]);
                       leveleditor_menu->item[3].kind = MN_GOTO;
                       le_level = 1;
-                      arrays_init();
-                      loadshared();
-                      le_current_level = new st_level;
-                      if(level_load(le_current_level, le_level_subset.name.c_str(), le_level) != 0)
+                      le_world.arrays_free();
+                      le_current_level = new Level;
+                      if(le_current_level->load(le_level_subset.name.c_str(), le_level) != 0)
                         {
                           le_quit();
                           return 1;
                         }
-                      le_update_buttons(le_current_level->theme.c_str());
                       le_set_defaults();
-                      level_load_gfx(le_current_level);
+                      le_current_level->load_gfx();
+                     le_world.activate_bad_guys();
                       show_menu = true;
                     }
                   break;
@@ -243,18 +272,17 @@ int leveleditor(int levelnb)
                       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 = new st_level;
-                      if(level_load(le_current_level, le_level_subset.name.c_str(), le_level) != 0)
+                      le_world.arrays_free();
+                      le_current_level = new Level;
+                      if(le_current_level->load(le_level_subset.name.c_str(), le_level) != 0)
                         {
                           le_quit();
                           return 1;
                         }
-                      le_update_buttons(le_current_level->theme.c_str());
                       le_set_defaults();
-                      level_load_gfx(le_current_level);
-                      menu_item_change_input(&subset_new_menu->item[2],"");
+                      le_current_level->load_gfx();
+                     le_world.activate_bad_guys();
+                      subset_new_menu->item[2].change_input("");
                       show_menu = true;
                       break;
                     }
@@ -291,6 +319,8 @@ int leveleditor(int levelnb)
           return 1;
         }
 
+      ++global_frame_counter;
+       
       SDL_Delay(25);
       now_time = SDL_GetTicks();
       if (now_time < last_time + FPS)
@@ -302,59 +332,13 @@ int leveleditor(int levelnb)
   return done;
 }
 
-
-void le_update_buttons(const char *theme)
-{
-  int i;
-  char filename[1024];
-  char pathname[1024];
-  SDLKey key;
-  string_list_type bkgd_files;
-  string_list_type fgd_files;
-
-  sprintf(pathname,"images/themes/%s",theme);
-  bkgd_files =  dfiles(pathname,"bkgd-", NULL);
-  string_list_sort(&bkgd_files);
-
-  le_bkgd_panel.hidden = true;
-  key = SDLK_a;
-  for(i = 0; i < bkgd_files.num_items; ++i)
-    {
-      sprintf(filename,"%s/%s",pathname,bkgd_files.item[i]);
-      button_change_icon(&le_bkgd_panel.item[i],filename);
-    }
-
-  sprintf(pathname,"images/themes/%s",theme);
-  fgd_files =  dfiles(pathname,"solid", NULL);
-  string_list_sort(&fgd_files);
-  key = SDLK_a;
-  for(i = 0; i < fgd_files.num_items; ++i)
-    {
-      sprintf(filename,"%s/%s",pathname,fgd_files.item[i]);
-      button_change_icon(&le_fgd_panel.item[i],filename);
-    }
-
-  string_list_free(&fgd_files);
-  fgd_files =  dfiles(pathname,"brick", NULL);
-  string_list_sort(&fgd_files);
-
-  for(i = 0; i < fgd_files.num_items; ++i)
-    {
-      sprintf(filename,"%s/%s",pathname,fgd_files.item[i]);
-      button_change_icon(&le_fgd_panel.item[i+14],filename);
-    }
-}
-
 int le_init()
 {
   int i;
-  char filename[1024];
-  SDLKey key;
-  string_list_type fgd_files;
-  string_list_type bkgd_files;
-  string_list_type bad_files;
   level_subsets = dsubdirs("/levels", "info");
 
+  active_tm = TM_IA;
+  
   le_show_grid = true;
 
   /*  level_changed = NO;*/
@@ -368,116 +352,36 @@ int le_init()
   le_mouse_pressed[LEFT] = false;
   le_mouse_pressed[RIGHT] = false;
 
-  texture_load(&le_selection, datadir + "/images/leveleditor/select.png", USE_ALPHA);
+  le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
 
-  /* 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);
-  button_load(&le_previous_level_bt,"/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
-  button_load(&le_rubber_bt,"/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
-  button_load(&le_select_mode_one_bt,"/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
-  button_load(&le_select_mode_two_bt,"/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64);
-  button_load(&le_test_level_bt,"/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
-  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);
-
-  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 = true;
-  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);
-
-  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);
-    }
-
-  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)
-    {
-      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);
-    }
-
-  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 = true;
-  key = SDLK_a;
-  for(i = 0; i < bad_files.num_items; ++i)
-    {
-      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);
-    }
+  select_tilegroup_menu_effect.init(false);
 
+  /* Load buttons */
+  le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
+  le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F6,screen->w-32,32);
+  le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
+  le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
+  le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
+  le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
+  le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64);
+  le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
+  le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
+  le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
+  le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
+  le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,80);
+  
+  le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
+  le_tilemap_panel->set_button_size(32,10);
+  le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_F4,0,0),TM_BG);
+  le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_F4,0,0),TM_IA);
+  le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_F4,0,0),TM_FG); 
+  
   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);
@@ -522,18 +426,37 @@ int le_init()
   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_TEXTFIELD,"Author  ",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_NUMFIELD,"Top Red    ",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Top Green  ",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Top Blue   ",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Bottom Red ",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Bottom Green",0,0);
+  level_settings_menu->additem(MN_NUMFIELD,"Bottom 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 )
+    {
+
+      select_tilegroup_menu->additem(MN_ACTION,const_cast<char*>((*it).name.c_str()),0,0);
+      tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
+      i = 0;
+      for(std::vector<int>::iterator sit = (*it).tiles.begin(); sit != (*it).tiles.end(); ++sit, ++i)
+        tilegroups_map[(*it).name]->additem(new Button(const_cast<char*>(("images/tilesets/" + TileManager::instance()->get(*sit)->filenames[0]).c_str()), const_cast<char*>((*it).name.c_str()),(SDLKey)(i+'a'),0,0,32,32),(*sit));
+    }
+  select_tilegroup_menu->additem(MN_HL,"",0,0);
+
   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
 
   return 0;
@@ -544,37 +467,44 @@ 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());
+  level_settings_menu->item[2].change_input(le_current_level->name.c_str());
+  level_settings_menu->item[3].change_input(le_current_level->author.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)
+  string_list_copy(level_settings_menu->item[4].list, dsubdirs("images/themes", "solid0.png"));
+  string_list_copy(level_settings_menu->item[5].list, dfiles("music/",NULL, "-fast"));
+  string_list_copy(level_settings_menu->item[6].list, dfiles("images/background",NULL, NULL));
+  string_list_add_item(level_settings_menu->item[6].list,"");
+  if((i = string_list_find(level_settings_menu->item[4].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)
+  if((i = string_list_find(level_settings_menu->item[5].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)
+  if((i = string_list_find(level_settings_menu->item[6].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);
+  level_settings_menu->item[7].change_input(str);
   sprintf(str,"%d",le_current_level->time_left);
-  menu_item_change_input(&level_settings_menu->item[7], str);
+  level_settings_menu->item[8].change_input(str);
   sprintf(str,"%2.0f",le_current_level->gravity);
-  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);
-  sprintf(str,"%d",le_current_level->bkgd_green);
-  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);
+  level_settings_menu->item[9].change_input(str);
+  sprintf(str,"%d",le_current_level->bkgd_top.red);
+  level_settings_menu->item[10].change_input(str);
+  sprintf(str,"%d",le_current_level->bkgd_top.green);
+  level_settings_menu->item[11].change_input(str);
+  sprintf(str,"%d",le_current_level->bkgd_top.blue);
+  level_settings_menu->item[12].change_input(str);
+  sprintf(str,"%d",le_current_level->bkgd_bottom.red);
+  level_settings_menu->item[13].change_input(str);
+  sprintf(str,"%d",le_current_level->bkgd_bottom.green);
+  level_settings_menu->item[14].change_input(str);
+  sprintf(str,"%d",le_current_level->bkgd_bottom.blue);
+  level_settings_menu->item[15].change_input(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());
+  subset_settings_menu->item[2].change_input(le_level_subset.title.c_str());
+  subset_settings_menu->item[3].change_input(le_level_subset.description.c_str());
 }
 
 void apply_level_settings_menu()
@@ -583,34 +513,37 @@ void apply_level_settings_menu()
   i = false;
 
   le_current_level->name = level_settings_menu->item[2].input;
+  le_current_level->author = level_settings_menu->item[3].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[6].list)) != 0)
     {
-      le_current_level->bkgd_image = string_list_active(level_settings_menu->item[5].list);
+      le_current_level->bkgd_image = string_list_active(level_settings_menu->item[6].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[4].list)) != 0)
     {
-      le_current_level->theme = string_list_active(level_settings_menu->item[3].list);
-      le_update_buttons(le_current_level->theme.c_str());
+      le_current_level->theme = string_list_active(level_settings_menu->item[4].list);
       i = true;
     }
 
   if(i)
     {
-      level_free_gfx();
-      level_load_gfx(le_current_level);
+      le_current_level->free_gfx();
+      le_current_level->load_gfx();
     }
 
-  le_current_level->song_title = string_list_active(level_settings_menu->item[4].list);
-
-  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);
+  le_current_level->song_title = string_list_active(level_settings_menu->item[5].list);
+
+  le_current_level->change_size(atoi(level_settings_menu->item[7].input));
+  le_current_level->time_left = atoi(level_settings_menu->item[8].input);
+  le_current_level->gravity = atof(level_settings_menu->item[9].input);
+  le_current_level->bkgd_top.red = atoi(level_settings_menu->item[10].input);
+  le_current_level->bkgd_top.green = atoi(level_settings_menu->item[11].input);
+  le_current_level->bkgd_top.blue = atoi(level_settings_menu->item[12].input);
+  le_current_level->bkgd_bottom.red = atoi(level_settings_menu->item[13].input);
+  le_current_level->bkgd_bottom.green = atoi(level_settings_menu->item[14].input);
+  le_current_level->bkgd_bottom.blue = atoi(level_settings_menu->item[15].input);
 }
 
 void save_subset_settings_menu()
@@ -622,13 +555,12 @@ void save_subset_settings_menu()
 
 void le_goto_level(int levelnb)
 {
-  arrays_free();
-  arrays_init();
+  le_world.arrays_free();
 
-  level_free(le_current_level);
-  if(level_load(le_current_level, le_level_subset.name.c_str(), levelnb) != 0)
+  le_current_level->cleanup();
+  if(le_current_level->load(le_level_subset.name.c_str(), levelnb) != 0)
     {
-      level_load(le_current_level, le_level_subset.name.c_str(), le_level);
+      le_current_level->load(le_level_subset.name.c_str(), le_level);
     }
   else
     {
@@ -637,10 +569,10 @@ void le_goto_level(int levelnb)
 
   le_set_defaults();
 
-  le_update_buttons(le_current_level->theme.c_str());
+  le_current_level->free_gfx();
+  le_current_level->load_gfx();
 
-  level_free_gfx();
-  level_load_gfx(le_current_level);
+  le_world.activate_bad_guys();
 }
 
 void le_quit(void)
@@ -651,35 +583,32 @@ void le_quit(void)
 
   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
 
-  texture_free(&le_selection);
+  delete le_selection;
   delete leveleditor_menu;
   delete subset_load_menu;
   delete subset_new_menu;
   delete subset_settings_menu;
   delete level_settings_menu;
-  button_panel_free(&le_bkgd_panel);
-  button_panel_free(&le_fgd_panel);
-  button_panel_free(&le_bad_panel);
-  button_free(&le_save_level_bt);
-  button_free(&le_test_level_bt);
-  button_free(&le_next_level_bt);
-  button_free(&le_previous_level_bt);
-  button_free(&le_move_right_bt);
-  button_free(&le_move_left_bt);
-  button_free(&le_rubber_bt);
-  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);
+  delete select_tilegroup_menu;
+  delete le_save_level_bt;
+  delete le_exit_bt;
+  delete le_test_level_bt;
+  delete le_next_level_bt;
+  delete le_previous_level_bt;
+  delete le_move_right_bt;
+  delete le_move_left_bt;
+  delete le_rubber_bt;
+  delete le_select_mode_one_bt;
+  delete le_select_mode_two_bt;
+  delete le_settings_bt;
+  delete le_tilegroup_bt;
+  delete le_tilemap_panel;
 
   if(le_current_level != NULL)
     {
-      level_free_gfx();
-      level_free(le_current_level);
-      unloadshared();
-      arrays_free();
+      le_current_level->free_gfx();
+      le_current_level->cleanup();
+      le_world.arrays_free();
     }
 }
 
@@ -701,7 +630,7 @@ void le_drawinterface()
     }
 
   if(le_selection_mode == CURSOR)
-    texture_draw(&le_selection, cursor_x - pos_x, cursor_y);
+    le_selection->draw( cursor_x - pos_x, cursor_y);
   else if(le_selection_mode == SQUARE)
     {
       int w, h;
@@ -718,63 +647,40 @@ void le_drawinterface()
 
   /* draw button bar */
   fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
-  drawshape(19 * 32, 14 * 32, le_current_tile);
-  switch(le_current_tile)
-    {
-    case 'B':
-      texture_draw(&img_mints, 19 * 32, 14 * 32);
-      break;
-    case '!':
-      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);
-      break;
-    case '0':
-      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);
-      break;
-    case '2':
-      texture_draw(&img_money_left[0],19 * 32, 14 * 32);
-      break;
-    default:
-      break;
-    }
+  Tile::draw(19 * 32, 14 * 32, le_current_tile);
+  
+       if(TileManager::instance()->get(le_current_tile)->editor_images.size() > 0)
+       TileManager::instance()->get(le_current_tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
 
   if(le_current_level != NULL)
     {
-      button_draw(&le_save_level_bt);
-      button_draw(&le_test_level_bt);
-      button_draw(&le_next_level_bt);
-      button_draw(&le_previous_level_bt);
-      button_draw(&le_rubber_bt);
-      button_draw(&le_select_mode_one_bt);
-      button_draw(&le_select_mode_two_bt);
-      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);
+      le_save_level_bt->draw();
+      le_exit_bt->draw();
+      le_test_level_bt->draw();
+      le_next_level_bt->draw();
+      le_previous_level_bt->draw();
+      le_rubber_bt->draw();
+      le_select_mode_one_bt->draw();
+      le_select_mode_two_bt->draw();
+      le_settings_bt->draw();
+      le_move_right_bt->draw();
+      le_move_left_bt->draw();
+      le_tilegroup_bt->draw();
+      if(!cur_tilegroup.empty())
+      tilegroups_map[cur_tilegroup]->draw();
+      le_tilemap_panel->draw();
 
       sprintf(str, "%d/%d", le_level,le_level_subset.levels);
-      text_drawf(&white_text, str, -8, 16, A_RIGHT, A_TOP, 1);
+      white_text->drawf(str, -10, 16, A_RIGHT, A_TOP, 0);
 
-      text_draw(&white_small_text, "F1 for Help", 10, 430, 1);
+      white_small_text->draw("F1 for Help", 10, 430, 1);
     }
   else
     {
       if(show_menu == false)
-        text_draw(&white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
+        white_small_text->draw("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);
+        white_small_text->draw("No Level Subset loaded", 10, 430, 1);
     }
 
 }
@@ -782,17 +688,20 @@ void le_drawinterface()
 void le_drawlevel()
 {
   unsigned int y,x,i,s;
+  Uint8 a;
 
   /* 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);
-      texture_draw_part(&img_bkgd,0,0,screen->w - s - 32 ,0,s,img_bkgd.h);
+      le_current_level->img_bkgd->draw_part(s,0,0,0,
+                                            le_current_level->img_bkgd->w - s - 32, le_current_level->img_bkgd->h);
+      le_current_level->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
+                                            le_current_level->img_bkgd->h);
     }
   else
     {
-      clearscreen(le_current_level->bkgd_red, le_current_level->bkgd_green, le_current_level->bkgd_blue);
+          drawgradient(le_current_level->bkgd_top, le_current_level->bkgd_bottom);
     }
 
   /*       clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
@@ -800,51 +709,55 @@ 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->ia_tiles[y][x + (int)(pos_x / 32)]);
-
+      
+       if(active_tm == TM_BG)
+       a = 255;
+       else
+       a = 128;
+      
+       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->bg_tiles[y][x + (int)(pos_x / 32)],a);
+       
+       if(active_tm == TM_IA)
+       a = 255;
+       else
+       a = 128;
+       
+        Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)],a);
+
+       if(active_tm == TM_FG)
+       a = 255;
+       else
+       a = 128;
+       
+       Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->fg_tiles[y][x + (int)(pos_x / 32)],a);
+       
         /* draw whats inside stuff when cursor is selecting those */
         /* (draw them all the time - is this the right behaviour?) */
-        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);
-            break;
-          case '!':
-            texture_draw(&img_golden_herring, x * 32 - ((int)pos_x % 32), y*32);
-            break;
-          case 'x':
-          case 'y':
-          case 'A':
-            texture_draw(&img_distro[(global_frame_counter / 5) % 4], x * 32 - ((int)pos_x % 32), y*32);
-            break;
-          default:
-            break;
-          }
+       if(TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images.size() > 0)
+       TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
+
       }
 
   /* Draw the Bad guys: */
-  for (i = 0; i < bad_guys.size(); ++i)
+  for (i = 0; i < le_world.bad_guys.size(); ++i)
     {
       /* 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);
-      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);
-      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);
+      
+      scroll_x = pos_x;
+      le_world.bad_guys[i].draw();
     }
 
 
   /* Draw the player: */
-  /* for now, the position is fixed at (0, 240) */
-  texture_draw(&tux_right[(global_frame_counter / 5) % 3], 0 - pos_x, 240);
+  /* for now, the position is fixed at (100, 240) */
+  tux_right[(global_frame_counter / 5) % 3]->draw( 100 - pos_x, 240);
 }
 
 void le_checkevents()
 {
   SDLKey key;
   SDLMod keymod;
-  button_type* pbutton;
+  Button* pbutton;
   int x,y;
 
   keymod = SDL_GetModState();
@@ -852,9 +765,9 @@ void le_checkevents()
   while(SDL_PollEvent(&event))
     {
       if(show_menu)
-          menu_event(event);
+        current_menu->event(event);
       else
-          mouse_cursor->set_state(MC_NORMAL);
+        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 &&
@@ -961,7 +874,9 @@ void le_checkevents()
                   selection.y2 = event.motion.y;
                 }
               else if(event.button.button == SDL_BUTTON_RIGHT)
+               {
                 le_mouse_pressed[RIGHT] = true;
+               }
               break;
             case SDL_MOUSEBUTTONUP:
               if(event.button.button == SDL_BUTTON_LEFT)
@@ -1009,14 +924,20 @@ void le_checkevents()
               if(show_menu == false)
                 {
                   /* Check for button events */
-                  button_event(&le_test_level_bt,&event);
-                  if(button_get_state(&le_test_level_bt) == BUTTON_CLICKED)
+                  le_test_level_bt->event(event);
+                  if(le_test_level_bt->get_state() == BUTTON_CLICKED)
                     le_testlevel();
-                  button_event(&le_save_level_bt,&event);
-                  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) == BUTTON_CLICKED)
+                  le_save_level_bt->event(event);
+                  if(le_save_level_bt->get_state() == BUTTON_CLICKED)
+                    le_current_level->save(le_level_subset.name.c_str(),le_level);
+                  le_exit_bt->event(event);
+                  if(le_exit_bt->get_state() == BUTTON_CLICKED)
+                 {
+                   Menu::set_current(leveleditor_menu);
+                   show_menu = true;
+                   }
+                  le_next_level_bt->event(event);
+                  if(le_next_level_bt->get_state() == BUTTON_CLICKED)
                     {
                       if(le_level < le_level_subset.levels)
                         {
@@ -1024,13 +945,13 @@ void le_checkevents()
                         }
                       else
                         {
-                          st_level new_lev;
+                          Level new_lev;
                           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);
-                          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);
+                          white_text->drawf(str,0,-18,A_HMIDDLE,A_VMIDDLE,2);
+                          white_text->drawf("Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2);
+                          red_text->drawf("(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2);
                           flipscreen();
                           while(d == 0)
                             {
@@ -1041,8 +962,8 @@ void le_checkevents()
                                     switch(event.key.keysym.sym)
                                       {
                                       case SDLK_y:
-                                        level_default(&new_lev);
-                                        level_save(&new_lev,le_level_subset.name.c_str(),++le_level);
+                                        new_lev.init_defaults();
+                                        new_lev.save(le_level_subset.name.c_str(),++le_level);
                                         le_level_subset.levels = le_level;
                                         le_goto_level(le_level);
                                         d = 1;
@@ -1061,182 +982,100 @@ void le_checkevents()
                             }
                         }
                     }
-                  button_event(&le_previous_level_bt,&event);
-                  if(button_get_state(&le_previous_level_bt) == BUTTON_CLICKED)
+                  le_previous_level_bt->event(event);
+                  if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
                     {
                       if(le_level > 1)
                         le_goto_level(--le_level);
                     }
-                  button_event(&le_rubber_bt,&event);
-                  if(button_get_state(&le_rubber_bt) == BUTTON_CLICKED)
+                  le_rubber_bt->event(event);
+                  if(le_rubber_bt->get_state() == BUTTON_CLICKED)
                     le_current_tile = 0;
-                  button_event(&le_select_mode_one_bt,&event);
-                  if(button_get_state(&le_select_mode_one_bt) == BUTTON_CLICKED)
+                  le_select_mode_one_bt->event(event);
+                  if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
                     le_selection_mode = CURSOR;
-                  button_event(&le_select_mode_two_bt,&event);
-                  if(button_get_state(&le_select_mode_two_bt) == BUTTON_CLICKED)
+                  le_select_mode_two_bt->event(event);
+                  if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
                     le_selection_mode = SQUARE;
 
-                  button_event(&le_bad_bt,&event);
-                  if(button_get_state(&le_bad_bt) == BUTTON_CLICKED)
+                  le_tilegroup_bt->event(event);
+                  if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
                     {
-                      le_bad_panel.hidden = false;
-                      le_fgd_panel.hidden = true;
-                      le_bkgd_panel.hidden = true;
+                      Menu::set_current(select_tilegroup_menu);
+                      select_tilegroup_menu_effect.start(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) == BUTTON_CLICKED)
-                    {
-                      le_bad_panel.hidden = true;
-                      le_fgd_panel.hidden = false;
-                      le_bkgd_panel.hidden = true;
-                    }
-                  button_event(&le_bkgd_bt,&event);
-                  if(button_get_state(&le_bkgd_bt) == BUTTON_CLICKED)
-                    {
-                      le_bad_panel.hidden = true;
-                      le_fgd_panel.hidden = true;
-                      le_bkgd_panel.hidden = false;
-                    }
-                  button_event(&le_settings_bt,&event);
-                  if(button_get_state(&le_settings_bt) == BUTTON_CLICKED)
-                    {
-                      if(show_menu == false)
-                        {
-                          update_level_settings_menu();
-                          Menu::set_current(level_settings_menu);
-                          show_menu = true;
-                        }
-                      else
-                        {
-                          Menu::set_current(leveleditor_menu);
-                          show_menu = false;
-                        }
-                    }
-                  if((pbutton = button_panel_event(&le_bkgd_panel,&event)) != NULL)
+                  le_settings_bt->event(event);
+                  if(le_settings_bt->get_state() == BUTTON_CLICKED)
                     {
-                      if(button_get_state(pbutton) == BUTTON_CLICKED)
-                        {
-                          char c = '\0';
-                          if(pbutton->tag >= 0 && pbutton->tag <= 3)
-                            c = 'G' + pbutton->tag;
-                          else if(pbutton->tag >= 4 && pbutton->tag <= 7)
-                            c = 'g' + pbutton->tag - 4;
-                          else if(pbutton->tag >= 8 && pbutton->tag <= 11)
-                            c = 'C' + pbutton->tag - 8;
-                          else if(pbutton->tag >= 12 && pbutton->tag <= 15)
-                            c = 'c' + pbutton->tag - 12;
-                          if(c != '\0')
-                            le_current_tile = c;
-                        }
-                    }
-                  if((pbutton = button_panel_event(&le_fgd_panel,&event)) != NULL)
-                    {
-                      if(button_get_state(pbutton) == BUTTON_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) == BUTTON_CLICKED)
-                        {
-                          char c = '\0';
-                          if(pbutton->tag >= 0 && pbutton->tag <= 2)
-                            c = '0' + pbutton->tag;
-                          if(c != '\0')
-                            le_current_tile = c;
-                        }
+                      update_level_settings_menu();
+                      Menu::set_current(level_settings_menu);
+                      show_menu = true;
                     }
+                 if(!cur_tilegroup.empty())
+                 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
+                 {
+                   if(pbutton->get_state() == BUTTON_CLICKED)
+                     {
+                     le_current_tile = pbutton->get_tag();
+                     }
+                 }
+                 if((pbutton = le_tilemap_panel->event(event)) != NULL)
+                 {
+                   if(pbutton->get_state() == BUTTON_CLICKED)
+                     {
+                     active_tm = static_cast<TileMapType>(pbutton->get_tag());
+                     }
+                 }
                 }
               else
                 {
-                  button_event(&le_settings_bt,&event);
-                  if(button_get_state(&le_settings_bt) == BUTTON_CLICKED)
+                  le_settings_bt->event(event);
+                  if(le_settings_bt->get_state() == BUTTON_CLICKED)
                     {
-                      if(show_menu == false)
-                        {
-                          update_level_settings_menu();
-                          Menu::set_current(level_settings_menu);
-                          show_menu = true;
-                        }
-                      else
-                        {
-                          Menu::set_current(leveleditor_menu);
-                          show_menu = false;
-                        }
+                      Menu::set_current(leveleditor_menu);
+                      show_menu = false;
+                    }
+                  le_tilegroup_bt->event(event);
+                  if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
+                    {
+                      Menu::set_current(leveleditor_menu);
+                      show_menu = false;
                     }
                 }
             }
           if(show_menu == false)
             {
-              button_event(&le_move_left_bt,&event);
-              button_event(&le_move_right_bt,&event);
+              le_move_left_bt->event(event);
+              le_move_right_bt->event(event);
 
               if(le_mouse_pressed[LEFT])
                 {
-                  le_change(cursor_x, cursor_y, TM_IA, le_current_tile);
+                  le_change(cursor_x, cursor_y, active_tm, le_current_tile);
                 }
             }
         }
     }
   if(show_menu == false)
     {
-      if(button_get_state(&le_move_left_bt) == BUTTON_PRESSED)
+      if(le_move_left_bt->get_state() == BUTTON_PRESSED)
         {
           pos_x -= 192;
         }
-      else if(button_get_state(&le_move_left_bt) == BUTTON_HOVER)
+      else if(le_move_left_bt->get_state() == BUTTON_HOVER)
         {
-          pos_x -= 96;
+          pos_x -= 64;
         }
 
-      if(button_get_state(&le_move_right_bt) == BUTTON_PRESSED)
+      if(le_move_right_bt->get_state() == BUTTON_PRESSED)
         {
           pos_x += 192;
         }
-      else if(button_get_state(&le_move_right_bt) == BUTTON_HOVER)
+      else if(le_move_right_bt->get_state() == BUTTON_HOVER)
         {
-          pos_x += 96;
+          pos_x += 64;
         }
     }
 
@@ -1288,22 +1127,22 @@ void le_change(float x, float y, int tm, unsigned int c)
       switch(le_selection_mode)
         {
         case CURSOR:
-          level_change(le_current_level,x,y,tm,c);
+          le_current_level->change(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 < 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]));
+          for(i = 0; i < le_world.bad_guys.size(); ++i)
+            if(xx == le_world.bad_guys[i].base.x/32 && yy == le_world.bad_guys[i].base.y/32)
+              le_world.bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&le_world.bad_guys[i]));
 
           if(c == '0')  /* if it's a bad guy */
-            add_bad_guy(xx*32, yy*32, BAD_BSOD);
+            le_world.add_bad_guy(xx*32, yy*32, BAD_BSOD);
           else if(c == '1')
-            add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
+            le_world.add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
           else if(c == '2')
-            add_bad_guy(xx*32, yy*32, BAD_MONEY);
+            le_world.add_bad_guy(xx*32, yy*32, BAD_MONEY);
 
           break;
         case SQUARE:
@@ -1334,22 +1173,22 @@ void le_change(float x, float y, int tm, unsigned int c)
           y2 /= 32;
 
           /* if there is a bad guy over there, remove it */
-          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(i = 0; i < le_world.bad_guys.size(); ++i)
+            if(le_world.bad_guys[i].base.x/32 >= x1 && le_world.bad_guys[i].base.x/32 <= x2
+               && le_world.bad_guys[i].base.y/32 >= y1 && le_world.bad_guys[i].base.y/32 <= y2)
+              le_world.bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&le_world.bad_guys[i]));
 
           for(xx = x1; xx <= x2; xx++)
             for(yy = y1; yy <= y2; yy++)
               {
-                level_change(le_current_level, xx*32, yy*32, tm, c);
+                le_current_level->change(xx*32, yy*32, tm, c);
 
                 if(c == '0')  // if it's a bad guy
-                  add_bad_guy(xx*32, yy*32, BAD_BSOD);
+                  le_world.add_bad_guy(xx*32, yy*32, BAD_BSOD);
                 else if(c == '1')
-                  add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
+                  le_world.add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
                 else if(c == '2')
-                  add_bad_guy(xx*32, yy*32, BAD_MONEY);
+                  le_world.add_bad_guy(xx*32, yy*32, BAD_MONEY);
               }
           break;
         default:
@@ -1360,12 +1199,15 @@ void le_change(float x, float y, int tm, unsigned int c)
 
 void le_testlevel()
 {
-  level_save(le_current_level,"test",le_level);
-  gameloop("test",le_level, ST_GL_TEST);
+  le_current_level->save("test", le_level);
+  
+  GameSession session("test",le_level, ST_GL_TEST);
+  session.run();
+
   Menu::set_current(leveleditor_menu);
-  arrays_init();
-  level_load_gfx(le_current_level);
-  loadshared();
+  le_world.arrays_free();
+  le_current_level->load_gfx();
+  le_world.activate_bad_guys();
 }
 
 void le_showhelp()
@@ -1404,12 +1246,12 @@ void le_showhelp()
                  };
 
 
-  text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
+  blue_text->drawf("- 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);
+    white_text->draw(text[i], 5, 80+(i*18), 1);
 
-  text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
+  gold_text->drawf("Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
 
   flipscreen();
 
@@ -1417,16 +1259,7 @@ void le_showhelp()
 
   while(done == 0)
     {
-      while(SDL_PollEvent(&event))
-        switch(event.type)
-          {
-          case SDL_MOUSEBUTTONDOWN:            // mouse pressed
-          case SDL_KEYDOWN:            // key pressed
-            done = 1;
-            break;
-          default:
-            break;
-          }
+      done = wait_for_event(event);
       SDL_Delay(50);
     }
 }