credits music plays on credits screen now
[supertux.git] / src / leveleditor.cpp
index f17fbe1..1f1692d 100644 (file)
 #include "leveleditor.h"
 #include "resources.h"
 #include "tile.h"
-#include "tilemap.h"
 #include "tile_manager.h"
 #include "sector.h"
-#include "background.h"
 #include "gameloop.h"
-#include "badguy.h"
-#include "gameobjs.h"
-#include "camera.h"
+#include "object_factory.h"
+#include "object/gameobjs.h"
+#include "object/camera.h"
+#include "object/tilemap.h"
+#include "object/background.h"
 
 LevelEditor::LevelEditor()
 {
   show_grid = true;
 
   selection.clear();
-  global_frame_counter = 0;
   selection_end = selection_ini = Vector(0,0);
   left_button = middle_button = mouse_moved =  false;
   level = 0;
@@ -103,47 +102,31 @@ LevelEditor::LevelEditor()
   tiles_board = new ButtonGroup(Vector(screen->w - 140, 100),
             Vector(32,32), Vector(4,8));
 
-  TileManager* tilemanager = TileManager::instance();
-
   tiles_board->add_button(Button(img_rubber_bt, _("Eraser"), SDLKey(SDLK_DELETE)), 0);
-  for(unsigned int id = 1; id < tilemanager->get_max_tileid(); id++)
+  unsigned int id;
+  for(id = 1; id < tile_manager->get_max_tileid(); id++)
     {
-    const Tile* tile = tilemanager->get(id);
+    const Tile* tile = tile_manager->get(id);
     if(!tile)
       continue;
 
-    Surface* surface;
-    if(tile->editor_images.size())
-      surface = tile->editor_images[0];
-    else if(tile->images.size())
-      surface = tile->images[0];
-    else
+    Surface* surface = tile->get_editor_image();
+    if(!surface)
       continue;
 
     Button button = Button(surface, "", SDLKey(0));
     tiles_board->add_button(button, id);
     }
-
-  #if 0
-  for(int i = 0; i < NUM_BadGuyKinds; i++)
-    {
-    // filter bomb, since it is only for internal use, not for levels
-    if(i == BAD_BOMB)
-      continue;
-
-    BadGuyKind kind = BadGuyKind(i);
-    BadGuy badguy(kind, 0,0);
-    badguy.activate(LEFT);
-
-    Surface *img = badguy.get_image();
-    tiles_board->add_button(Button(img, "", SDLKey(SDLK_1+i)), -(i+1));
-    }
-  #endif
-
-  #if 0
-  tiles_board->add_button(Button(img_trampoline[0].get_frame(0), _("Trampoline"), SDLKey(0)), OBJ_TRAMPOLINE);
-  tiles_board->add_button(Button(img_flying_platform->get_frame(0), _("Flying Platform"), SDLKey(0)), OBJ_FLYING_PLATFORM);
-  #endif
+  gameobjs_first_id = id;
+
+  for(Factories::iterator i = object_factories->begin();
+      i != object_factories->end(); ++i) {
+    
+//    Surface *img = badguy.get_image();
+// FIXME: get image from object. Using the rubber in the meanwhile.
+    tiles_board->add_button(Button(img_rubber_bt, i->first,
+                            SDLKey(SDLK_1+id)), id++);
+  }
 
   tiles_layer = new ButtonGroup(Vector(12, screen->h-64), Vector(80,20), Vector(1,3));
   tiles_layer->add_button(Button(img_foreground_bt, _("Edtit foreground tiles"),
@@ -233,7 +216,6 @@ else
 
 mouse_cursor->set_state(MC_NORMAL);
 
-frame_timer.start(.25, true);
 done = false;
 while(!done)
   {
@@ -291,7 +273,9 @@ while(SDL_PollEvent(&event))
         level_subset->description = create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).input;
         //FIXME: generate better level filenames
         level_subset->add_level(subset_name+'/'+"new_level.stl");
-        Level::create(level_subset->get_level_filename(0));
+        Level* newlevel = new Level();
+        newlevel->add_sector(create_sector("main", 25, 19));
+        newlevel->save(level_subset->get_level_filename(0));
         level_subset->save();
         
         load_level(0);
@@ -371,7 +355,9 @@ while(SDL_PollEvent(&event))
           if(confirm_dialog(NULL, str))
             {
             level_subset->add_level("new_level.stl");
-            Level::create(level_subset->get_level_filename(level_nb + 1));
+            Level* newlevel = new Level();
+            newlevel->add_sector(create_sector("main", 25, 19));
+            newlevel->save(level_subset->get_level_filename(level_nb + 1));
             level_subset->save();
             load_level(level_nb + 1);
             }
@@ -458,7 +444,7 @@ std::cerr << "previous sector.\n";
               {
               vector.push_back(tilemap->get_tile(x +
                (int)(((selection_ini.x+scroll.x)*zoom)/32),
-               y + (int)(((selection_ini.y+scroll.y)*zoom)/32))->id);
+               y + (int)(((selection_ini.y+scroll.y)*zoom)/32))->getID());
               }
             selection.push_back(vector);
             }
@@ -535,10 +521,6 @@ if(tiles_board->is_hover() || tiles_layer->is_hover() || level_options->is_hover
 
 if(sector)
   {
-    if(frame_timer.check()) {
-      ++global_frame_counter;
-    }
-
   // don't scroll before the start or after the level's end
   float width = sector->solids->get_width() * 32;
   float height = sector->solids->get_height() * 32;
@@ -617,11 +599,12 @@ if(sector)
       if(selection[0][0] == 0 && selection.size() == 1)
           context.draw_surface(img_rubber_bt, Vector(event.button.x - 8,
           event.button.y - 8), LAYER_GUI-2);
-      else if(selection[0][0] < 0)
+      else if(selection[0][0] >= gameobjs_first_id || selection[0][0] < 0)
         {
+// FIXME: this should draw an object image near cursor
+#if 0
         int id = selection[0][0];
 
-#if 0
         if(id == OBJ_TRAMPOLINE)
           context.draw_surface(img_trampoline[0].get_frame(0), Vector(event.button.x - 8,
           event.button.y - 8), LAYER_GUI-2);
@@ -629,14 +612,12 @@ if(sector)
           context.draw_surface(img_flying_platform->get_frame(0), Vector(event.button.x - 8,
           event.button.y - 8), LAYER_GUI-2);
         else
-#endif
         if(id == OBJ_DOOR)
           /*context.draw_surface(door->get_frame(0), Vector(event.button.x - 8,
           event.button.y - 8), LAYER_GUI-2);*/
           ;
         else
           {
-#if 0
           BadGuyKind kind = BadGuyKind((-id)-1);
           BadGuy badguy(kind, 0,0);
           badguy.activate(LEFT);
@@ -644,15 +625,14 @@ if(sector)
 
           context.draw_surface(img, Vector(event.button.x - 8,
           event.button.y - 8), LAYER_GUI-2);
-#endif
           }
+#endif
         }
       else
         {
-        TileManager* tilemanager = TileManager::instance();
         for(unsigned int x = 0; x < selection.size(); x++)
           for(unsigned int y = 0; y < selection[x].size(); y++) {
-            const Tile* tile = tilemanager->get(selection[x][y]);
+            const Tile* tile = tile_manager->get(selection[x][y]);
             tile->draw(context,
                 Vector(event.button.x + x*32 - 8, event.button.y + y*32 - 8),
                 LAYER_GUI-2);
@@ -787,7 +767,7 @@ if(sector_ == NULL)
   {
   if(!confirm_dialog(NULL, _("No more sectors exist. Create another?")))
     return;
-  sector_ = Sector::create("new_sector",25,19);
+  sector_ = create_sector("new_sector",25,19);
   level->add_sector(sector_);
   }
 
@@ -801,12 +781,6 @@ foregrounds = solids = backgrounds = 0;
 /* Point foregrounds, backgrounds, solids to its layer */
 for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); i++)
   {
-#if 0
-  BadGuy* badguy = dynamic_cast<BadGuy*> (*i);
-  if(badguy)
-    badguy->activate(LEFT);
-#endif
-
   TileMap* tilemap = dynamic_cast<TileMap*> (*i);
   if(tilemap)
     {
@@ -862,6 +836,7 @@ void LevelEditor::test_level()
 
 void LevelEditor::change(int x, int y, int newtile, int layer)
 {  
+  (void) layer;
   // find the tilemap of the current layer, and then change the tile
   if(x < 0 || (unsigned int)x >= sector->solids->get_width()*32 ||
       y < 0 || (unsigned int)y >= sector->solids->get_height()*32)
@@ -870,29 +845,31 @@ void LevelEditor::change(int x, int y, int newtile, int layer)
   level_changed = true;
   
   if(zoom != 1)
-  {  // no need to do this for normal view (no zoom)
+  { 
+    // no need to do this for normal view (no zoom)
     x = (int)(x * (zoom*32) / 32);
     y = (int)(y * (zoom*32) / 32);
   }
 
-  if(newtile < 0)  // add object
+  if(newtile >= gameobjs_first_id)  // add object
   {
     // remove an active tile or object that might be there
     change(x, y, 0, LAYER_TILES);
 
-#if 0
-    if(newtile == OBJ_TRAMPOLINE)
-      sector->add_object(new Trampoline(x, y));
-    else if(newtile == OBJ_FLYING_PLATFORM)
-      sector->add_object(new FlyingPlatform(x, y));
-    else
-      if(newtile == OBJ_DOOR)
-        sector->add_object(new Door(x, y));
-      else
-        sector->add_bad_guy(x, y, BadGuyKind((-newtile)-1), true);
-#endif
-
-    sector->update_game_objects();
+    int id = 0;
+    GameObject* object = 0;
+    for(Factories::iterator i = object_factories->begin(); i !=
+        object_factories->end(); ++i) {
+      if(id == newtile - gameobjs_first_id) {
+        object = create_object(i->first, Vector(x, y));
+        break;
+      }
+      id++;
+    }
+    if(object) {
+      sector->add_object(object);
+      sector->update_game_objects();
+    }
   } else if(cur_layer == LAYER_FOREGROUNDTILES) {
     foregrounds->change(x/32, y/32, newtile);
   } else if(cur_layer == LAYER_TILES) {
@@ -900,13 +877,12 @@ void LevelEditor::change(int x, int y, int newtile, int layer)
     // we /32 in order to round numbers
     for(Sector::GameObjects::iterator i = sector->gameobjects.begin();
         i < sector->gameobjects.end(); i++) {
+// FIXME: if there is a game objs in here, remove it!
 #if 0
       BadGuy* badguy = dynamic_cast<BadGuy*> (*i);
       if(badguy)
         if((int)badguy->base.x/32 == x/32 && (int)badguy->base.y/32 == y/32)
           sector->gameobjects.erase(i);
-#endif
-#if 0
       Trampoline* trampoline = dynamic_cast<Trampoline*> (*i);
       if(trampoline)
       {
@@ -917,8 +893,6 @@ void LevelEditor::change(int x, int y, int newtile, int layer)
       if(flying_platform)
         if((int)flying_platform->base.x/32 == x/32 && (int)flying_platform->base.y/32 == y/32)
           sector->gameobjects.erase(i);
-#endif
-#if 0
       Door* door = dynamic_cast<Door*> (*i);
       if(door)
         if((int)door->get_area().x/32 == x/32 && (int)door->get_area().y/32 == y/32)
@@ -941,7 +915,7 @@ mouse_cursor->set_state(MC_HIDE);
 
 
 char str[1024];
-char *text1[] = {
+const char *text1[] = {
          _("This is the built-in level editor. Its aim is to be intuitive\n"
          "and simple to use, so it should be pretty straightforward.\n"
          "\n"
@@ -977,7 +951,7 @@ char *text1[] = {
          "enemies and game objects in the bottom.\n")
                 };
 
-char *text2[] = {
+const char *text2[] = {
          _("The Foreground/Interactive/Background buttons may be used to\n"
          "see and edit the respective layer. Levels have three tiles layers:\n"
          "Foreground - tiles are drawn on top of everything and have no contact\n"
@@ -1010,7 +984,7 @@ char *text2[] = {
          "Webpage: http://pingus.seul.org/~grumbel/flexlay/")
                 };
 
-char **text[] = { text1, text2 };
+const char **text[] = { text1, text2 };
 
 
 bool done;
@@ -1039,3 +1013,19 @@ for(unsigned int i = 0; i < sizeof(text) / sizeof(text[0]); i++)
 show_grid = show_grid_t;
 mouse_cursor->set_state(MC_NORMAL);
 }
+
+Sector*
+LevelEditor::create_sector(const std::string& name, size_t width, size_t height)
+{
+  Sector* sector = new Sector;
+  sector->set_name(name);
+  
+  sector->add_object(new TileMap(LAYER_BACKGROUNDTILES, false, width, height));
+  sector->add_object(new TileMap(LAYER_TILES, true, width, height));
+  sector->add_object(new TileMap(LAYER_FOREGROUNDTILES, false, width, height));
+  sector->add_object(new Camera(sector));
+  sector->update_game_objects();
+  
+  return sector;
+}
+