- converted text_type into a class
[supertux.git] / src / leveleditor.cpp
index d7ddc42..e18011d 100644 (file)
 #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();
@@ -80,45 +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_tilegroup_bt;
+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_type select_tilegroup_menu_effect;
-static std::map<std::string, button_panel_type > tilegroups_map;
+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()
 {
@@ -156,9 +157,10 @@ int leveleditor(int levelnb)
 
       if(current_menu == select_tilegroup_menu)
         {
-          if(timer_check(&select_tilegroup_menu_effect))
+          if(select_tilegroup_menu_effect.check())
             {
-              select_tilegroup_menu->set_pos(screen->w - 64 + timer_get_left(&select_tilegroup_menu_effect),82,-0.5,0.5);
+              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);
@@ -203,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;
@@ -240,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;
@@ -271,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;
                     }
@@ -319,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)
@@ -330,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;*/
@@ -396,23 +352,30 @@ 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);
 
-  timer_init(&select_tilegroup_menu_effect,false);
+  select_tilegroup_menu_effect.init(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);
-  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_tilegroup_bt,"/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,82);
-
+  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();
@@ -463,15 +426,19 @@ 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);
 
@@ -483,9 +450,10 @@ int le_init()
     {
 
       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));
+      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);
 
@@ -499,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()
@@ -538,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()
@@ -577,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
     {
@@ -592,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)
@@ -606,31 +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;
   delete select_tilegroup_menu;
-  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_tilegroup_bt);
+  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();
     }
 }
 
@@ -652,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;
@@ -669,59 +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_tilegroup_bt);
-      button_panel_draw(&tilegroups_map[cur_tilegroup]);
+      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);
     }
 
 }
@@ -729,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); */
@@ -747,51 +709,55 @@ void le_drawlevel()
   for (y = 0; y < 15; ++y)
     for (x = 0; x < 20; ++x)
       {
-        drawshape(32*x - fmodf(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();
@@ -799,7 +765,7 @@ void le_checkevents()
   while(SDL_PollEvent(&event))
     {
       if(show_menu)
-        menu_event(event);
+        current_menu->event(event);
       else
         mouse_cursor->set_state(MC_NORMAL);
 
@@ -908,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)
@@ -956,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)
                         {
@@ -971,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)
                             {
@@ -988,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;
@@ -1008,73 +982,64 @@ 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_tilegroup_bt,&event);
-                  if(button_get_state(&le_tilegroup_bt) == BUTTON_CLICKED)
+                  le_tilegroup_bt->event(event);
+                  if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
                     {
                       Menu::set_current(select_tilegroup_menu);
-                      timer_start(&select_tilegroup_menu_effect,200);
+                      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_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)
                     {
                       update_level_settings_menu();
                       Menu::set_current(level_settings_menu);
                       show_menu = true;
                     }
-                 if((pbutton = button_panel_event(&tilegroups_map[cur_tilegroup],&event)) != NULL)
+                 if(!cur_tilegroup.empty())
+                 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
                  {
-                   if(button_get_state(pbutton) == BUTTON_CLICKED)
+                   if(pbutton->get_state() == BUTTON_CLICKED)
                      {
-                     le_current_tile = pbutton->tag;
+                     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());
                      }
                  }
-                  /*if((pbutton = button_panel_event(&le_bkgd_panel,&event)) != NULL)
-                    {
-                      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;
-                        }
-                    }*/
                 }
               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)
                     {
                       Menu::set_current(leveleditor_menu);
                       show_menu = false;
                     }
-                  button_event(&le_tilegroup_bt,&event);
-                  if(button_get_state(&le_tilegroup_bt) == BUTTON_CLICKED)
+                  le_tilegroup_bt->event(event);
+                  if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
                     {
                       Menu::set_current(leveleditor_menu);
                       show_menu = false;
@@ -1083,34 +1048,34 @@ void le_checkevents()
             }
           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;
         }
     }
 
@@ -1162,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:
@@ -1208,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:
@@ -1234,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()
@@ -1278,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();
 
@@ -1291,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);
     }
 }