- Reworked Surface class and drawing stuff:
authorMatthias Braun <matze@braunis.de>
Mon, 3 Oct 2005 15:29:22 +0000 (15:29 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 3 Oct 2005 15:29:22 +0000 (15:29 +0000)
    - colors and alpha values are floats now
    - No complicated SurfaceData/SurfaceImpl stuff anymore
    - Loaded images are cached and reused

SVN-Revision: 2806

57 files changed:
data/images/engine/fonts/numbers.png [deleted file]
data/images/engine/fonts/shadow-big.png [new file with mode: 0644]
data/images/engine/fonts/shadow-small.png [new file with mode: 0644]
data/images/engine/fonts/shadow.png [new file with mode: 0644]
data/levels/world2/dfk-level3.stl
data/levels/world2/level2.stl
src/badguy/badguy.cpp
src/flip_level_transformer.cpp
src/game_session.cpp
src/gui/button.cpp
src/gui/menu.cpp
src/gui/mousecursor.cpp
src/gui/mousecursor.hpp
src/lisp/writer.cpp
src/lisp/writer.hpp
src/main.cpp
src/object/ambient_sound.cpp
src/object/background.cpp
src/object/display_effect.cpp
src/object/fireworks.cpp
src/object/gameobjs.hpp
src/object/level_time.cpp
src/object/particlesystem.cpp
src/object/particlesystem_interactive.cpp
src/object/platform.cpp
src/object/text_object.cpp
src/object/tilemap.cpp
src/object/tilemap.hpp
src/player_status.cpp
src/resources.cpp
src/resources.hpp
src/sector.cpp
src/sprite/sprite.cpp
src/sprite/sprite.hpp
src/sprite/sprite_data.cpp
src/textscroller.cpp
src/tile.cpp
src/tile.hpp
src/tile_manager.cpp
src/tile_manager.hpp
src/title.cpp
src/video/color.hpp [new file with mode: 0644]
src/video/drawing_context.cpp
src/video/drawing_context.hpp
src/video/font.cpp
src/video/font.hpp
src/video/image_texture.cpp [new file with mode: 0644]
src/video/image_texture.hpp [new file with mode: 0644]
src/video/screen.cpp
src/video/screen.hpp
src/video/surface.cpp
src/video/surface.hpp
src/video/texture.cpp
src/video/texture.hpp
src/video/texture_manager.cpp [new file with mode: 0644]
src/video/texture_manager.hpp [new file with mode: 0644]
src/worldmap.cpp

diff --git a/data/images/engine/fonts/numbers.png b/data/images/engine/fonts/numbers.png
deleted file mode 100644 (file)
index 8ac3083..0000000
Binary files a/data/images/engine/fonts/numbers.png and /dev/null differ
diff --git a/data/images/engine/fonts/shadow-big.png b/data/images/engine/fonts/shadow-big.png
new file mode 100644 (file)
index 0000000..72354f7
Binary files /dev/null and b/data/images/engine/fonts/shadow-big.png differ
diff --git a/data/images/engine/fonts/shadow-small.png b/data/images/engine/fonts/shadow-small.png
new file mode 100644 (file)
index 0000000..4b25a25
Binary files /dev/null and b/data/images/engine/fonts/shadow-small.png differ
diff --git a/data/images/engine/fonts/shadow.png b/data/images/engine/fonts/shadow.png
new file mode 100644 (file)
index 0000000..b7e0544
Binary files /dev/null and b/data/images/engine/fonts/shadow.png differ
index d3c7286..03fe7e7 100644 (file)
 
        (spawnpoint (name "main") (x 64) (y 11040))
        (background
-         (top_color 0 0 50)
-         (bottom_color 0 0 150)
+         (top_color 0 0 0.2)
+         (bottom_color 0 0 0.6)
          (speed 1.000000)
        )
        (particles-clouds
     )
 
        (background
-         (top_color 0 0 50)
-         (bottom_color 0 0 150)
+         (top_color 0 0 0.2)
+         (bottom_color 0 0 0.6)
          (speed 1.000000)
        )
        (particles-clouds
index 3797a4b..aeb103d 100644 (file)
       (bonusblock (x 672) (y 1056)
         (contents "custom")
         (powerup
-          (sprite "red-potion")
+          (sprite "images/powerups/potions/red-potion.sprite")
           (script "levelflip();")
         )
       )
       (powerup (x 8608) (y 1024)
-        (sprite "red-potion")
+        (sprite "images/powerups/potions/red-potion.sprite")
         (script "levelflip();")
       )
       (powerup (x 9952) (y 416)
-        (sprite "red-potion")
+        (sprite "images/powerups/potions/red-potion.sprite")
         (script "levelflip();")
       )
       (powerup (x 8000) (y 352)
index 308e3e9..700904e 100644 (file)
@@ -47,8 +47,8 @@ BadGuy::draw(DrawingContext& context)
   if(state == STATE_INIT || state == STATE_INACTIVE)
     return;
   if(state == STATE_FALLING) {
-    uint32_t old_effect = context.get_drawing_effect();
-    context.set_drawing_effect(old_effect | VERTICAL_FLIP);
+    DrawingEffect old_effect = context.get_drawing_effect();
+    context.set_drawing_effect((DrawingEffect) (old_effect | VERTICAL_FLIP));
     sprite->draw(context, get_pos(), LAYER_OBJECTS);
     context.set_drawing_effect(old_effect);
   } else {
index 73fe33b..1b88399 100644 (file)
@@ -80,7 +80,7 @@ FlipLevelTransformer::transform_tilemap(TileMap* tilemap)
     }
   }
   if(tilemap->get_drawing_effect() != 0) {
-    tilemap->set_drawing_effect(0);
+    tilemap->set_drawing_effect(NO_EFFECT);
   } else {
     tilemap->set_drawing_effect(VERTICAL_FLIP);
   }
index 2aa3036..a18a774 100644 (file)
@@ -457,12 +457,17 @@ GameSession::draw_pause()
           -((pause_menu_frame * i)%SCREEN_WIDTH)
           ,(i*20+pause_menu_frame)%SCREEN_HEIGHT),
         Vector(SCREEN_WIDTH,10),
-        Color(20,20,20, rand() % 20 + 1), LAYER_FOREGROUND1+1);
+        Color(0.1, 0.1, 0.1, static_cast<float>(rand() % 20 + 1) / 255.0),
+        LAYER_FOREGROUND1+1);
   }
 
   context->draw_filled_rect(
       Vector(0,0), Vector(SCREEN_WIDTH, SCREEN_HEIGHT),
-      Color(rand() % 50, rand() % 50, rand() % 50, 128), LAYER_FOREGROUND1);
+      Color(
+        static_cast<float>(rand() % 50) / 255.0,
+        static_cast<float>(rand() % 50) / 255.0,
+        static_cast<float>(rand() % 50) / 255.0,
+        0.5), LAYER_FOREGROUND1);
 #if 0
   context->draw_text(blue_text, _("PAUSE - Press 'P' To Play"),
       Vector(SCREEN_WIDTH/2, 230), CENTER_ALLIGN, LAYER_FOREGROUND1+2);
index 16d901d..2e4a336 100644 (file)
@@ -37,7 +37,7 @@ Button::Button(Surface* image_, std::string info_, SDLKey binding_)
   : binding(binding_)
 {
   image = image_;
-  size = Vector(image->w, image->h);
+  size = Vector(image->get_width(), image->get_height());
   id = 0;
   info = info_;
 }
index 37d74c6..5993bf4 100644 (file)
@@ -84,7 +84,8 @@ bool confirm_dialog(Surface *background, std::string text)
       }
 
       if(background == NULL)
-        context.draw_gradient(Color(200,240,220), Color(200,200,220), LAYER_BACKGROUND0);
+        context.draw_gradient(Color(0.8, 0.95, 0.85), Color(0.8, 0.8, 0.8),
+                              LAYER_BACKGROUND0);
       else
         context.draw_surface(background, Vector(0,0), LAYER_BACKGROUND0);
 
@@ -537,9 +538,11 @@ Menu::draw_item(DrawingContext& context, int index)
         int y = y_pos - 12 - effect_offset;
         /* Draw a horizontal line with a little 3d effect */
         context.draw_filled_rect(Vector(x, y + 6),
-                                 Vector(menu_width, 4), Color(150,200,255,225), LAYER_GUI);
+                                 Vector(menu_width, 4),
+                                 Color(0.6f, 0.7f, 1.0f, 1.0f), LAYER_GUI);
         context.draw_filled_rect(Vector(x, y + 6),
-                                 Vector(menu_width, 2), Color(255,255,255,255), LAYER_GUI);
+                                 Vector(menu_width, 2),
+                                 Color(1.0f, 1.0f, 1.0f, 1.0f), LAYER_GUI);
         break;
       }
     case MN_LABEL:
@@ -560,11 +563,11 @@ Menu::draw_item(DrawingContext& context, int index)
         context.draw_filled_rect(
           Vector(input_pos - 5, y_pos - 10),
           Vector(input_width + 10, 20),
-          Color(255,255,255,255), LAYER_GUI-5);
+          Color(1.0f, 1.0f, 1.0f, 1.0f), LAYER_GUI-5);
         context.draw_filled_rect(
           Vector(input_pos - 4, y_pos - 9),
           Vector(input_width + 8, 18),
-          Color(0,0,0,128), LAYER_GUI-4);
+          Color(0, 0, 0, 0.5f), LAYER_GUI-4);
 
         if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD)
           {
@@ -607,11 +610,11 @@ Menu::draw_item(DrawingContext& context, int index)
         context.draw_filled_rect(
           Vector(x_pos - list_pos + text_pos - 1, y_pos - 10),
           Vector(list_pos_2 + 2, 20),
-          Color(255,255,255,255), LAYER_GUI - 4);
+          Color(1.0f, 1.0f, 1.0f, 1.0f), LAYER_GUI - 4);
         context.draw_filled_rect(
           Vector(x_pos - list_pos + text_pos, y_pos - 9),
           Vector(list_pos_2, 18),
-          Color(0,0,0,128), LAYER_GUI - 5);
+          Color(0, 0, 0, 0.5f), LAYER_GUI - 5);
 
         context.draw_text(text_font, pitem.list[pitem.selected],
                                  Vector(SCREEN_WIDTH/2 + text_pos, y_pos - int(text_font->get_height()/2)),
@@ -701,7 +704,7 @@ Menu::draw(DrawingContext& context)
   context.draw_filled_rect(
     Vector(pos_x - menu_width/2, pos_y - 24*items.size()/2 - 10),
     Vector(menu_width,menu_height + 20),
-    Color(150,180,200,125), LAYER_GUI-10);
+    Color(0.6f, 0.7f, 0.8f, 0.5f), LAYER_GUI-10);
 
   for(unsigned int i = 0; i < items.size(); ++i)
     {
index d2a082e..51bf984 100644 (file)
@@ -27,7 +27,7 @@ extern SDL_Surface* screen;
 
 MouseCursor::MouseCursor(std::string cursor_file) : mid_x(0), mid_y(0)
 {
-  cursor = new Surface(cursor_file, true);
+  cursor = new Surface(cursor_file);
   
   cur_state = MC_NORMAL;
 
@@ -68,8 +68,8 @@ void MouseCursor::draw(DrawingContext& context)
   x = int(x * float(SCREEN_WIDTH)/screen->w);
   y = int(y * float(SCREEN_HEIGHT)/screen->h);
 
-  w = cursor->w;
-  h = cursor->h / MC_STATES_NB;
+  w = (int) cursor->get_width();
+  h = (int) (cursor->get_height() / MC_STATES_NB);
   if(ispressed &SDL_BUTTON(1) || ispressed &SDL_BUTTON(2)) {
     if(cur_state != MC_CLICK) {
       state_before_click = cur_state;
index 98f03c2..8ccfda8 100644 (file)
@@ -32,6 +32,8 @@ enum {
   MC_HIDE
 };
 
+class DrawingContext;
+
 /// Mouse cursor.
 /** Used to create mouse cursors.
     The mouse cursors can be animated
index 9312ea2..3969789 100644 (file)
@@ -143,6 +143,17 @@ Writer::write_int_vector(const std::string& name,
 }
 
 void
+Writer::write_float_vector(const std::string& name,
+                           const std::vector<float>& value)
+{
+  indent();
+  *out << '(' << name;
+  for(std::vector<float>::const_iterator i = value.begin(); i != value.end(); ++i)
+    *out << " " << *i;
+  *out << ")\n";
+}
+
+void
 Writer::indent()
 {
   for(int i = 0; i<indent_depth; ++i)
index 90baf12..40039dc 100644 (file)
@@ -45,6 +45,7 @@ namespace lisp
     void write_bool(const std::string& name, bool value);
     void write_int_vector(const std::string& name, const std::vector<int>& value);
     void write_int_vector(const std::string& name, const std::vector<unsigned int>& value);
+    void write_float_vector(const std::string& name, const std::vector<float>& value);
     // add more write-functions when needed...
 
     void end_list(const std::string& listname);
index 84b0e96..caf7812 100644 (file)
@@ -43,6 +43,7 @@
 #include "gettext.hpp"
 #include "audio/sound_manager.hpp"
 #include "video/surface.hpp"
+#include "video/texture_manager.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
 #include "misc.hpp"
 #include "title.hpp"
@@ -301,6 +302,9 @@ static void check_gl_error()
 
 void init_video()
 {
+  if(texture_manager != NULL)
+    texture_manager->save_textures();
+  
   SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
@@ -339,6 +343,9 @@ void init_video()
   // setup opengl state and transform
   glDisable(GL_DEPTH_TEST);
   glDisable(GL_CULL_FACE);
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
   glViewport(0, 0, screen->w, screen->h);
   glMatrixMode(GL_PROJECTION);
@@ -351,7 +358,10 @@ void init_video()
 
   check_gl_error();
 
-  Surface::reload_all();
+  if(texture_manager != NULL)
+    texture_manager->reload_textures();
+  else
+    texture_manager = new TextureManager();
 }
 
 static void init_audio()
@@ -450,15 +460,13 @@ int main(int argc, char** argv)
 
   free_menu();
   unload_shared();
-#ifdef DEBUG
-  Surface::debug_check();
-#endif
   quit_audio();
 
   if(config)
     config->save();
   delete config;
   delete main_controller;
+  delete texture_manager;
   SDL_Quit();
   PHYSFS_deinit();
   
index 68253b0..21ad67f 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <math.h>
 #include <stdexcept>
+#include <iostream>
 
 #include "ambient_sound.hpp"
 #include "object_factory.hpp"
index 4b8adc4..7c43cfa 100644 (file)
@@ -40,10 +40,11 @@ Background::Background(const lisp::Lisp& reader)
       && reader.get("speed", speed)) {
     set_image(imagefile, speed);
   } else {
-    std::vector <unsigned int> bkgd_top_color, bkgd_bottom_color;
+    std::vector<float> bkgd_top_color, bkgd_bottom_color;
     if(reader.get_vector("top_color", bkgd_top_color) &&
         reader.get_vector("bottom_color", bkgd_bottom_color))
-      set_gradient(Color(bkgd_top_color), Color(bkgd_bottom_color));
+      set_gradient(Color(bkgd_top_color),
+                   Color(bkgd_bottom_color));
   }
 }
 
@@ -64,15 +65,15 @@ Background::write(lisp::Writer& writer)
     writer.write_string("image", imagefile);
     writer.write_float("speed", speed);
   } else if(type == GRADIENT) {
-    std::vector <unsigned int> bkgd_top_color, bkgd_bottom_color;
+    std::vector<float> bkgd_top_color, bkgd_bottom_color;
     bkgd_top_color.push_back(gradient_top.red);
     bkgd_top_color.push_back(gradient_top.green);
     bkgd_top_color.push_back(gradient_top.blue);
     bkgd_bottom_color.push_back(gradient_top.red);
     bkgd_bottom_color.push_back(gradient_top.green);
     bkgd_bottom_color.push_back(gradient_top.blue);
-    writer.write_int_vector("top_color", bkgd_top_color);
-    writer.write_int_vector("bottom_color", bkgd_bottom_color);
+    writer.write_float_vector("top_color", bkgd_top_color);
+    writer.write_float_vector("bottom_color", bkgd_bottom_color);
   }
   writer.write_int("layer", layer);
   
@@ -92,7 +93,7 @@ Background::set_image(const std::string& name, float speed)
   this->speed = speed;
 
   delete image;
-  image = new Surface("images/background/" + name, false);
+  image = new Surface("images/background/" + name);
 }
 
 void
@@ -103,7 +104,7 @@ Background::set_gradient(Color top, Color bottom)
   gradient_bottom = bottom;
 
   delete image;
-  image = new Surface(top, bottom, SCREEN_WIDTH, SCREEN_HEIGHT);
+  image = NULL;
 }
 
 void
@@ -112,18 +113,20 @@ Background::draw(DrawingContext& context)
   if(type == GRADIENT) {
     context.push_transform();
     context.set_translation(Vector(0, 0));
-    context.draw_surface(image, Vector(0, 0), layer);
+    context.draw_gradient(gradient_top, gradient_bottom, layer);
     context.pop_transform();
   } else if(type == IMAGE) {
     if(!image)
       return;
     
-    int sx = int(-context.get_translation().x * speed) % image->w - image->w;
-    int sy = int(-context.get_translation().y * speed) % image->h - image->h;
+    int w = (int) image->get_width();
+    int h = (int) image->get_height();
+    int sx = int(-context.get_translation().x * speed) % w - w;
+    int sy = int(-context.get_translation().y * speed) % h - h;
     context.push_transform();
     context.set_translation(Vector(0, 0));
-    for(int x = sx; x < SCREEN_WIDTH; x += image->w)
-      for(int y = sy; y < SCREEN_HEIGHT; y += image->h)
+    for(int x = sx; x < SCREEN_WIDTH; x += w)
+      for(int y = sy; y < SCREEN_HEIGHT; y += h)
         context.draw_surface(image, Vector(x, y), layer);
     context.pop_transform();
   }
index 7bf875b..1f67b43 100644 (file)
@@ -56,18 +56,16 @@ DisplayEffect::draw(DrawingContext& context)
     context.set_translation(Vector(0, 0));
 
     if(black || type != NO_FADE) {    
-      uint8_t alpha;
+      float alpha;
       if(black) {
-          alpha = 255;
+          alpha = 1.0f;
       } else {
           switch(type) {
               case FADE_IN:
-                  alpha = static_cast<uint8_t>
-                      (fading * 255.0 / fadetime);
+                  alpha = fading / fadetime;
                   break;
               case FADE_OUT:
-                  alpha = static_cast<uint8_t>
-                      ((fadetime-fading) * 255.0 / fadetime);
+                  alpha = (fadetime-fading) / fadetime;
                   break;
               default:
                   alpha = 0;
@@ -80,9 +78,9 @@ DisplayEffect::draw(DrawingContext& context)
 
     if (borders_fading || borders_active) {
       context.draw_filled_rect(Vector(0, 0), Vector(SCREEN_WIDTH, border_size),
-              Color(0, 0, 0, 255), LAYER_GUI-10);
+              Color(0, 0, 0, 1.0f), LAYER_GUI-10);
       context.draw_filled_rect(Vector(0, SCREEN_HEIGHT - border_size), Vector(SCREEN_WIDTH, border_size),
-              Color(0, 0, 0, 255), LAYER_GUI-10);
+              Color(0, 0, 0, 1.0f), LAYER_GUI-10);
     }
 
     context.pop_transform();
@@ -129,3 +127,4 @@ DisplayEffect::four_to_three()
 {
   borders_fading = false;
 }
+
index 62904c5..7047bf9 100644 (file)
@@ -46,8 +46,8 @@ Fireworks::update(float )
         pos += Vector(SCREEN_WIDTH * ((float) rand() / RAND_MAX),
                       SCREEN_HEIGHT/2 * ((float) rand() / RAND_MAX));
 
-        int red = rand() % 255;
-        int green = rand() % red;
+        float red = static_cast<float>(rand() % 255) / 255.0;
+        float green = static_cast<float>(rand() % ((int) red*255)) / 255.0;
         sector->add_object(new Particles(pos, 0, 360, Vector(140, 140),
                 Vector(0, 0), 45, Color(red, green, 0), 3, 1.3,
                 LAYER_FOREGROUND1+1));
index 4aa1fa9..53e8b48 100644 (file)
@@ -27,6 +27,7 @@
 #include "game_object.hpp"
 #include "moving_object.hpp"
 #include "serializable.hpp"
+#include "video/color.hpp"
 
 /* Bounciness of distros: */
 #define NO_BOUNCE 0
index 591df80..532afc5 100644 (file)
@@ -3,6 +3,7 @@
 #include "level_time.hpp"
 
 #include <stdexcept>
+#include <iostream>
 #include "main.hpp"
 #include "resources.hpp"
 #include "sector.hpp"
index 5edb5a4..c9b484b 100644 (file)
@@ -73,9 +73,9 @@ void ParticleSystem::draw(DrawingContext& context)
 
 SnowParticleSystem::SnowParticleSystem()
 {
-    snowimages[0] = new Surface("images/objects/particles/snow0.png", true);
-    snowimages[1] = new Surface("images/objects/particles/snow1.png", true);
-    snowimages[2] = new Surface("images/objects/particles/snow2.png", true);
+    snowimages[0] = new Surface("images/objects/particles/snow0.png");
+    snowimages[1] = new Surface("images/objects/particles/snow1.png");
+    snowimages[2] = new Surface("images/objects/particles/snow2.png");
 
     virtual_width = SCREEN_WIDTH * 2;
 
@@ -133,8 +133,8 @@ void SnowParticleSystem::update(float elapsed_time)
 //       Ghosts don't change their movement pattern - not random
 GhostParticleSystem::GhostParticleSystem()
 {
-    ghosts[0] = new Surface("images/objects/particles/ghost0.png", true);
-    ghosts[1] = new Surface("images/objects/particles/ghost1.png", true);
+    ghosts[0] = new Surface("images/objects/particles/ghost0.png");
+    ghosts[1] = new Surface("images/objects/particles/ghost1.png");
 
     virtual_width = SCREEN_WIDTH * 2;
 
@@ -190,7 +190,7 @@ void GhostParticleSystem::update(float elapsed_time)
 
 CloudParticleSystem::CloudParticleSystem()
 {
-    cloudimage = new Surface("images/objects/particles/cloud.png", true);
+    cloudimage = new Surface("images/objects/particles/cloud.png");
 
     virtual_width = 2000.0;
 
index 5bdf862..edb2cbc 100644 (file)
@@ -142,8 +142,8 @@ ParticleSystem_Interactive::collision(Particle* object, Vector movement)
 
 RainParticleSystem::RainParticleSystem()
 {
-    rainimages[0] = new Surface("images/objects/particles/rain0.png", true);
-    rainimages[1] = new Surface("images/objects/particles/rain1.png", true);
+    rainimages[0] = new Surface("images/objects/particles/rain0.png");
+    rainimages[1] = new Surface("images/objects/particles/rain1.png");
 
     virtual_width = SCREEN_WIDTH * 2;
 
@@ -224,8 +224,8 @@ void RainParticleSystem::update(float elapsed_time)
 
 CometParticleSystem::CometParticleSystem()
 {
-    cometimages[0] = new Surface("images/creatures/mr_bomb/exploding-left-0.png", true);
-    cometimages[1] = new Surface("images/creatures/mr_bomb/exploding-left-0.png", true);
+    cometimages[0] = new Surface("images/creatures/mr_bomb/exploding-left-0.png");
+    cometimages[1] = new Surface("images/creatures/mr_bomb/exploding-left-0.png");
 
     virtual_width = SCREEN_WIDTH * 2;
 
index 9bbc5fe..c0a59a7 100644 (file)
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-
 #include <config.h>
 
 #include "platform.hpp"
+
+#include <iostream>
 #include "video/drawing_context.hpp"
 #include "resources.hpp"
 #include "player.hpp"
index 9d2dd33..348d934 100644 (file)
@@ -1,6 +1,8 @@
 #include <config.h>
 
 #include "text_object.hpp"
+
+#include <iostream>
 #include "resources.hpp"
 #include "video/drawing_context.hpp"
 
@@ -74,17 +76,16 @@ TextObject::draw(DrawingContext& context)
   context.push_transform();
   context.set_translation(Vector(0, 0));
   if(fading > 0) {
-    context.set_alpha(static_cast<uint8_t> 
-        ((fadetime-fading) * 255.0 / fadetime));
+    context.set_alpha((fadetime-fading) / fadetime);
   } else if(fading < 0) {
-    context.set_alpha(static_cast<uint8_t> (-fading * 255.0 / fadetime));
+    context.set_alpha(-fading / fadetime);
   } else if(!visible) {
     context.pop_transform();
     return;
   }
 
   context.draw_filled_rect(Vector(125, 50), Vector(550, 120),
-      Color(150, 180, 200, 125), LAYER_GUI-50);
+      Color(0.6, 0.7, 0.8, 0.5), LAYER_GUI-50);
   if (centered) {
     context.draw_center_text(font, text, Vector(0, 50+35), LAYER_GUI-40);
   }
index 8775418..a6765ee 100644 (file)
@@ -37,7 +37,7 @@
 
 TileMap::TileMap()
   : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
-    drawing_effect(0)
+    drawing_effect(NO_EFFECT)
 {
   tilemanager = tile_manager;
 
@@ -47,7 +47,7 @@ TileMap::TileMap()
 
 TileMap::TileMap(const lisp::Lisp& reader, TileManager* new_tile_manager)
   : solid(false), speed(1), width(-1), height(-1), layer(LAYER_TILES),
-    drawing_effect(0)
+    drawing_effect(NO_EFFECT)
 {
   tilemanager = new_tile_manager;
   if(tilemanager == 0)
@@ -94,7 +94,7 @@ TileMap::TileMap(const lisp::Lisp& reader, TileManager* new_tile_manager)
 
 TileMap::TileMap(int layer_, bool solid_, size_t width_, size_t height_)
   : solid(solid_), speed(1), width(0), height(0), layer(layer_),
-    drawing_effect(0)
+    drawing_effect(NO_EFFECT)
 {
   tilemanager = tile_manager;
   
@@ -180,13 +180,13 @@ TileMap::draw(DrawingContext& context)
     for (pos.x = start_x; pos.x < end_x; pos.x += 32)
     {
        context.draw_filled_rect(Vector (pos.x, start_y), Vector(1, fabsf(start_y - end_y)),
-                  Color(225, 225, 225), LAYER_GUI-50);
+                  Color(0.8f, 0.8f, 0.8f), LAYER_GUI-50);
     }
 
     for (pos.y = start_y; pos.y < end_y; pos.y += 32)
     {
        context.draw_filled_rect(Vector (start_x, pos.y), Vector(fabsf(start_x - end_x), 1),
-                  Color(225, 225, 225), LAYER_GUI-50);
+                  Color(1.0f, 1.0f, 1.0f), LAYER_GUI-50);
     }
   }
 #endif
index e344fa0..8219623 100644 (file)
@@ -25,6 +25,7 @@
 #include "game_object.hpp"
 #include "serializable.hpp"
 #include "math/vector.hpp"
+#include "video/drawing_context.hpp"
 
 namespace lisp {
 class Lisp;
@@ -87,12 +88,12 @@ public:
     return tilemanager;
   }
 
-  void set_drawing_effect(int effect)
+  void set_drawing_effect(DrawingEffect effect)
   {
     drawing_effect = effect;
   }
 
-  int get_drawing_effect()
+  DrawingEffect get_drawing_effect()
   {
     return drawing_effect;
   }
@@ -108,7 +109,7 @@ private:
   int width, height;
   int layer;
 
-  int drawing_effect;
+  DrawingEffect drawing_effect;
 };
 
 #endif /*SUPERTUX_TILEMAP_H*/
index 29ed5bb..1367c98 100644 (file)
@@ -209,7 +209,7 @@ PlayerStatus::draw(DrawingContext& context)
 
   if (player_status->lives >= 5) {
     sprintf(str, "%dx", player_status->lives);
-    float x = SCREEN_WIDTH - gold_text->get_text_width(str) - tux_life->w;
+    float x = SCREEN_WIDTH - gold_text->get_text_width(str) - tux_life->get_width();
     context.draw_text(gold_text, str, Vector(x - BORDER_X, BORDER_Y + 20), LEFT_ALLIGN,
                       LAYER_FOREGROUND1);
     context.draw_surface(tux_life, Vector(SCREEN_WIDTH - 16 - BORDER_X, BORDER_Y + 20),
@@ -217,7 +217,8 @@ PlayerStatus::draw(DrawingContext& context)
   } else {
     for(int i= 0; i < player_status->lives; ++i)
       context.draw_surface(tux_life, 
-          Vector(SCREEN_WIDTH - tux_life->w*4 +(tux_life->w*i) - BORDER_X, BORDER_Y + 20),
+          Vector(SCREEN_WIDTH - tux_life->get_width()*4 +(tux_life->get_width()*i) - BORDER_X,
+                 BORDER_Y + 20),
           LAYER_FOREGROUND1);
   }
 
index 92f2f41..e1ac72f 100644 (file)
@@ -35,7 +35,6 @@ MouseCursor* mouse_cursor = 0;
 Font* gold_text;
 Font* blue_text;
 Font* gray_text;
-Font* yellow_nums;
 Font* white_text;
 Font* white_small_text;
 Font* white_big_text;                              
@@ -44,26 +43,29 @@ Font* white_big_text;
 void load_shared()
 {
   /* Load GUI/menu images: */
-  checkbox = new Surface("images/engine/menu/checkbox-unchecked.png", true);
-  checkbox_checked = new Surface("images/engine/menu/checkbox-checked.png", true);
-  back = new Surface("images/engine/menu/arrow-back.png", true);
-  arrow_left = new Surface("images/engine/menu/arrow-left.png", true);
-  arrow_right = new Surface("images/engine/menu/arrow-right.png", true);
+  checkbox = new Surface("images/engine/menu/checkbox-unchecked.png");
+  checkbox_checked = new Surface("images/engine/menu/checkbox-checked.png");
+  back = new Surface("images/engine/menu/arrow-back.png");
+  arrow_left = new Surface("images/engine/menu/arrow-left.png");
+  arrow_right = new Surface("images/engine/menu/arrow-right.png");
 
   /* Load the mouse-cursor */
   mouse_cursor = new MouseCursor("images/engine/menu/mousecursor.png");
   MouseCursor::set_current(mouse_cursor);
 
   /* Load global images: */
-  gold_text = new Font("images/engine/fonts/gold.png", Font::TEXT, 16,18);
-  blue_text = new Font("images/engine/fonts/blue.png", Font::TEXT, 16,18,3);
-  white_text  = new Font("images/engine/fonts/white.png", Font::TEXT, 16,18);
-  gray_text  = new Font("images/engine/fonts/gray.png", Font::TEXT, 16,18);
+  gold_text = new Font("images/engine/fonts/gold.png",
+                       "images/engine/fonts/shadow.png", 16, 18);
+  blue_text = new Font("images/engine/fonts/blue.png", 
+                       "images/engine/fonts/shadow.png", 16, 18, 3);
+  white_text = new Font("images/engine/fonts/white.png",
+                        "images/engine/fonts/shadow.png", 16, 18);
+  gray_text = new Font("images/engine/fonts/gray.png",
+                       "images/engine/fonts/shadow.png", 16, 18);
   white_small_text = new Font("images/engine/fonts/white-small.png",
-                              Font::TEXT, 8,9, 1);
-  white_big_text   = new Font("images/engine/fonts/white-big.png",
-                              Font::TEXT, 20,22, 3);
-  yellow_nums = new Font("images/engine/fonts/numbers.png", Font::NUM, 32,32);
+                              "images/engine/fonts/shadow-small.png", 8, 9, 1);
+  white_big_text = new Font("images/engine/fonts/white-big.png",
+                            "images/engine/fonts/shadow-big.png", 20, 22, 3);
 
   Menu::default_font = white_text;
   Menu::active_font = blue_text;
@@ -81,10 +83,10 @@ void load_shared()
   for (int i = 0; i < GROWING_FRAMES; i++)
     {
       sprintf(img_name, "images/creatures/tux_grow/left-%i.png", i+1);
-      growingtux_left[i] = new Surface(img_name, true);
+      growingtux_left[i] = new Surface(img_name);
 
       sprintf(img_name, "images/creatures/tux_grow/right-%i.png", i+1);
-      growingtux_right[i] = new Surface(img_name, true);
+      growingtux_right[i] = new Surface(img_name);
     }
 
   small_tux = new TuxBodyParts();
@@ -115,7 +117,7 @@ void load_shared()
   load_object_gfx();
 
   /* Tux life: */
-  tux_life = new Surface("images/creatures/tux_small/tux-life.png", true);
+  tux_life = new Surface("images/creatures/tux_small/tux-life.png");
   
   player_status = new PlayerStatus();
 }
@@ -130,7 +132,6 @@ void unload_shared()
   delete gray_text;
   delete white_small_text;
   delete white_big_text;
-  delete yellow_nums;
   
   free_object_gfx();
 
index 30a6eb5..0263959 100644 (file)
@@ -50,7 +50,6 @@ extern Font* blue_text;
 extern Font* gray_text;
 extern Font* white_small_text;
 extern Font* white_big_text;
-extern Font* yellow_nums;
 
 void load_shared();
 void unload_shared();
index 79d80c6..9e3ae22 100644 (file)
@@ -201,16 +201,16 @@ Sector::parse_old_format(const lisp::Lisp& reader)
   reader.get("bkgd_red_top", r);
   reader.get("bkgd_green_top",  g);
   reader.get("bkgd_blue_top",  b);
-  bkgd_top.red = r;
-  bkgd_top.green = g;
-  bkgd_top.blue = b;
+  bkgd_top.red = static_cast<float> (r) / 255.0f;
+  bkgd_top.green = static_cast<float> (g) / 255.0f;
+  bkgd_top.blue = static_cast<float> (b) / 255.0f;
   
   reader.get("bkgd_red_bottom",  r);
   reader.get("bkgd_green_bottom", g);
   reader.get("bkgd_blue_bottom", b);
-  bkgd_bottom.red = r;
-  bkgd_bottom.green = g;
-  bkgd_bottom.blue = b;
+  bkgd_bottom.red = static_cast<float> (r) / 255.0f;
+  bkgd_bottom.green = static_cast<float> (g) / 255.0f;
+  bkgd_bottom.blue = static_cast<float> (b) / 255.0f;
   
   if(backgroundimage != "") {
     Background* background = new Background;
index 3dc91f2..5047546 100644 (file)
@@ -48,7 +48,7 @@ Sprite::~Sprite()
 }
 
 void
-Sprite::set_action(std::string name, int loops)
+Sprite::set_action(const std::string& name, int loops)
 {
   if(action && action->name == name)
     return;
@@ -129,13 +129,13 @@ Sprite::draw_part(DrawingContext& context, const Vector& source,
 int
 Sprite::get_width() const
 {
-  return action->surfaces[get_frame()]->w;
+  return (int) action->surfaces[get_frame()]->get_width();
 }
 
 int
 Sprite::get_height() const
 {
-  return action->surfaces[get_frame()]->h;
+  return (int) action->surfaces[get_frame()]->get_height();
 }
 
 
index 9b1dee8..1c16632 100644 (file)
 #define SUPERTUX_SPRITE_H
 
 #include <string>
-#include <vector>
-#include <cassert>
-#include <map>
+#include <assert.h>
+#include <SDL.h>
 
 #include "video/surface.hpp"
 #include "math/vector.hpp"
 #include "sprite_data.hpp"
 
+class DrawingContext;
+
 class Sprite
 {
 public:
-       Sprite(SpriteData& data);
-       Sprite(const Sprite& other);
-       ~Sprite();
-       
-       /** Draw sprite, automatically calculates next frame */
-       void draw(DrawingContext& context, const Vector& pos, int layer);
-
-       void draw_part(DrawingContext& context, const Vector& source,
-           const Vector& size, const Vector& pos, int layer);
-
-       /** Set action (or state) */
-       void set_action(std::string act, int loops = -1);
-
-       /* Stop animation */
-       void stop_animation()
-       { animation_loops = 0; }
-       /** Check if animation is stopped or not */
-       bool check_animation();
-
-       float get_fps() const
-       { return action->fps; }
-       /** Get current action total frames */
-       int get_frames() const
-       { return action->surfaces.size(); }
-       /** Get sprite's name */
-       const std::string& get_name() const
-       { return data.name; }
-       /** Get current action name */
-       const std::string& get_action_name() const
-       { return action->name; }
-
-       int get_width() const;
-       int get_height() const;
-
-       /** Get current frame */
-       int get_frame() const
-       { return (int)frame; }
-       /** Set current frame */
-       void set_frame(int frame_)
-       { if(frame_ > get_frames()) frame = 0; else frame = frame_; }
-       Surface* get_frame(unsigned int frame)
-       {
-         assert(frame < action->surfaces.size());
-         return action->surfaces[frame];
-       }    
+  Sprite(SpriteData& data);
+  Sprite(const Sprite& other);
+  ~Sprite();
+
+  /** Draw sprite, automatically calculates next frame */
+  void draw(DrawingContext& context, const Vector& pos, int layer);
+
+  void draw_part(DrawingContext& context, const Vector& source,
+      const Vector& size, const Vector& pos, int layer);
+
+  /** Set action (or state) */
+  void set_action(const std::string& act, int loops = -1);
+
+  /* Stop animation */
+  void stop_animation()
+  { animation_loops = 0; }
+  /** Check if animation is stopped or not */
+  bool check_animation();
+
+  float get_fps() const
+  { return action->fps; }
+  /** Get current action total frames */
+  int get_frames() const
+  { return action->surfaces.size(); }
+  /** Get sprite's name */
+  const std::string& get_name() const
+  { return data.name; }
+  /** Get current action name */
+  const std::string& get_action_name() const
+  { return action->name; }
+
+  int get_width() const;
+  int get_height() const;
+
+  /** Get current frame */
+  int get_frame() const
+  { return (int)frame; }
+  /** Set current frame */
+  void set_frame(int frame_)
+  { if(frame_ > get_frames()) frame = 0; else frame = frame_; }
+  Surface* get_frame(unsigned int frame)
+  {
+    assert(frame < action->surfaces.size());
+    return action->surfaces[frame];
+  }    
 
 private:
-       void update();
+  void update();
 
-       SpriteData& data;
+  SpriteData& data;
 
-       float frame;
-       int animation_loops;
-       Uint32 last_ticks;
+  float frame;
+  int animation_loops;
+  Uint32 last_ticks;
 
-       SpriteData::Action* action;
+  SpriteData::Action* action;
 };
 
 #endif
index 58d22cf..ca97124 100644 (file)
@@ -90,9 +90,8 @@ SpriteData::parse_action(const lisp::Lisp* lisp, const std::string& basedir)
     } else {
       for(int i = 0; static_cast<unsigned int>(i) < act_tmp->surfaces.size();
           i++) {
-        Surface* surface = new Surface(sdl_surface_from_sdl_surface(
-              act_tmp->surfaces[i]->impl->get_sdl_surface()), true);
-        surface->apply_filter(HORIZONTAL_FLIP_FILTER);
+        Surface* surface = new Surface(*(act_tmp->surfaces[i]));
+        surface->hflip();
         action->surfaces.push_back(surface);
       }
     }
@@ -106,7 +105,7 @@ SpriteData::parse_action(const lisp::Lisp* lisp, const std::string& basedir)
     }
 
     for(std::vector<std::string>::size_type i = 0; i < images.size(); i++) {
-      action->surfaces.push_back(new Surface(basedir + images[i], true));
+      action->surfaces.push_back(new Surface(basedir + images[i]));
     }
   }
   actions[action->name] = action;
index d76342a..0c44062 100644 (file)
@@ -98,13 +98,12 @@ void display_text_file(const std::string& filename)
     if(line[0] == '!') {
       std::string imagename = line.substr(1, line.size()-1);
       std::cout << "Imagename: " << imagename << "\n";
-      images.insert(std::make_pair(imagename, new Surface(imagename, true)));
+      images.insert(std::make_pair(imagename, new Surface(imagename)));
     }
   }
 
   // load background image
-  Surface* background 
-    = new Surface("images/background/" + background_file, false);
+  Surface* background = new Surface("images/background/" + background_file);
 
   bool done = false;
   float scroll = 0;
@@ -187,9 +186,9 @@ void display_text_file(const std::string& filename)
       }
       if(image != 0) {
         context.draw_surface(image,
-            Vector( (SCREEN_WIDTH - image->w) / 2,
+            Vector( (SCREEN_WIDTH - image->get_width()) / 2,
                     SCREEN_HEIGHT + y - scroll), 255);
-        y += image->h + ITEMS_SPACE;
+        y += image->get_height() + ITEMS_SPACE;
       }
     }
     
@@ -240,7 +239,7 @@ InfoBox::draw(DrawingContext& context)
   float height = 200;
   
   context.draw_filled_rect(Vector(x1, y1), Vector(width, height),
-      Color(150, 180, 200, 125), LAYER_GUI-1);
+      Color(0.6f, 0.7f, 0.8f, 0.5f), LAYER_GUI-1);
 
   float y = y1;
   for(size_t i = firstline; i < lines.size(); ++i) {
index 6c75fb1..f2ec18a 100644 (file)
@@ -137,18 +137,18 @@ Tile::load_images(const std::string& tilesetpath)
     Surface* surface;
     std::string file = tilesetpath + spec.file;
     if(spec.rect.get_width() <= 0) {
-      surface = new Surface(file, true);
+      surface = new Surface(file);
     } else {
       surface = new Surface(file,
           (int) spec.rect.p1.x,
           (int) spec.rect.p1.y,
           (int) spec.rect.get_width(),
-          (int) spec.rect.get_height(), true);
+          (int) spec.rect.get_height());
     }
     images.push_back(surface);
   }
   if(editor_imagefile != "") {
-    editor_image = new Surface(tilesetpath + editor_imagefile, true);
+    editor_image = new Surface(tilesetpath + editor_imagefile);
   }
 }
 
index ed1196e..a551d30 100644 (file)
 #define TILE_H
 
 #include <vector>
+#include <SDL.h>
 #include "video/surface.hpp"
 #include "math/rect.hpp"
 #include "lisp/lisp.hpp"
 
+class DrawingContext;
+
 /**
 Tile Class
 */
@@ -115,7 +118,7 @@ public:
   { 
     if(!images.size())
       return 0;
-    return images[0]->w;
+    return (int) images[0]->get_width();
   }
 
   /// returns the height of the tiles in pixels
@@ -123,7 +126,7 @@ public:
   {
     if(!images.size())
       return 0;
-    return images[0]->h;
+    return (int) images[0]->get_height();
   }
 
 protected:
index 5e941d0..6ade3d9 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <memory>
 #include <stdexcept>
+#include <iostream>
 #include <assert.h>
 #include "video/drawing_context.hpp"
 #include "lisp/lisp.hpp"
index e5ab109..b8ef087 100644 (file)
@@ -25,6 +25,7 @@
 #include <vector>
 #include <string>
 #include <map>
+#include <iostream>
 #include <stdint.h>
 #include <assert.h>
 #include "tile.hpp"
index 266b28b..97efc08 100644 (file)
@@ -285,9 +285,9 @@ void title()
   titlesession = new GameSession("levels/misc/menu.stl", ST_GL_DEMO_GAME);
 
   /* Load images: */
-  bkg_title = new Surface("images/background/arctis.jpg", false);
-  logo = new Surface("images/engine/menu/logo.png", true);
-  //img_choose_subset = new Surface("images/status/choose-level-subset.png", true);
+  bkg_title = new Surface("images/background/arctis.jpg");
+  logo = new Surface("images/engine/menu/logo.png");
+  //img_choose_subset = new Surface("images/status/choose-level-subset.png");
 
   titlesession->get_current_sector()->activate("main");
   titlesession->set_current();
@@ -335,7 +335,7 @@ void title()
       draw_demo(elapsed_time);
 
       if (Menu::current() == main_menu)
-        context.draw_surface(logo, Vector(SCREEN_WIDTH/2 - logo->w/2, 30),
+        context.draw_surface(logo, Vector(SCREEN_WIDTH/2 - logo->get_width()/2, 30),
             LAYER_FOREGROUND1+1);
 
       context.draw_text(white_small_text, " SuperTux " PACKAGE_VERSION "\n",
diff --git a/src/video/color.hpp b/src/video/color.hpp
new file mode 100644 (file)
index 0000000..18f8849
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __COLOR_HPP__
+#define __COLOR_HPP__
+
+#include <vector>
+
+class Color
+{
+public:
+  Color()
+    : red(0), green(0), blue(0), alpha(1.0)
+  { }
+  Color(float red, float green, float blue, float alpha = 1.0)
+    : red(red), green(green), blue(blue), alpha(alpha)
+  { }
+  Color(const std::vector<float>& vals)
+  {
+    red = vals[0];
+    green = vals[1];
+    blue = vals[2];
+    if(vals.size() > 3)
+      alpha = vals[3];
+  }
+
+  float red, green, blue, alpha;
+};
+
+#endif
+
index 48b9c97..6f1aee1 100644 (file)
@@ -32,6 +32,7 @@
 #include "gameconfig.hpp"
 #include "glutil.hpp"
 #include "texture.hpp"
+#include "texture_manager.hpp"
 
 #define LIGHTMAP_DIV 4
 
@@ -50,19 +51,22 @@ DrawingContext::DrawingContext()
 
   lightmap_width = screen->w / LIGHTMAP_DIV;
   lightmap_height = screen->h / LIGHTMAP_DIV;
-  int width = next_po2(lightmap_width);
-  int height = next_po2(lightmap_height);
+  unsigned int width = next_po2(lightmap_width);
+  unsigned int height = next_po2(lightmap_height);
 
-  lightmap.reset(new Texture(width, height, GL_RGB));
+  lightmap = new Texture(width, height, GL_RGB);
 
   lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
   lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
+  texture_manager->register_texture(lightmap);
 
   requests = &drawing_requests;
 }
 
 DrawingContext::~DrawingContext()
 {
+  texture_manager->remove_texture(lightmap);
+  delete lightmap;
 }
 
 void
@@ -77,12 +81,12 @@ DrawingContext::draw_surface(const Surface* surface, const Vector& position,
   request.pos = transform.apply(position);
 
   if(request.pos.x >= SCREEN_WIDTH || request.pos.y >= SCREEN_HEIGHT
-      || request.pos.x + surface->w < 0 || request.pos.y + surface->h < 0)
+      || request.pos.x + surface->get_width() < 0 
+      || request.pos.y + surface->get_height() < 0)
     return;
 
   request.layer = layer;
   request.drawing_effect = transform.drawing_effect;
-  request.zoom = transform.zoom;
   request.alpha = transform.alpha;
   request.request_data = const_cast<Surface*> (surface);  
 
@@ -138,7 +142,6 @@ DrawingContext::draw_text(const Font* font, const std::string& text,
   request.pos = transform.apply(position);
   request.layer = layer;
   request.drawing_effect = transform.drawing_effect;
-  request.zoom = transform.zoom;
   request.alpha = transform.alpha;
 
   TextRequest* textrequest = new TextRequest;
@@ -159,7 +162,7 @@ DrawingContext::draw_center_text(const Font* font, const std::string& text,
 }
 
 void
-DrawingContext::draw_gradient(Color top, Color bottom, int layer)
+DrawingContext::draw_gradient(const Color& top, const Color& bottom, int layer)
 {
   DrawingRequest request;
 
@@ -168,7 +171,6 @@ DrawingContext::draw_gradient(Color top, Color bottom, int layer)
   request.layer = layer;
 
   request.drawing_effect = transform.drawing_effect;
-  request.zoom = transform.zoom;
   request.alpha = transform.alpha;
 
   GradientRequest* gradientrequest = new GradientRequest;
@@ -181,7 +183,7 @@ DrawingContext::draw_gradient(Color top, Color bottom, int layer)
 
 void
 DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size,
-        Color color, int layer)
+                                 const Color& color, int layer)
 {
   DrawingRequest request;
 
@@ -190,15 +192,12 @@ DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size,
   request.layer = layer;
 
   request.drawing_effect = transform.drawing_effect;
-  request.zoom = transform.zoom;
   request.alpha = transform.alpha;                    
 
   FillRectRequest* fillrectrequest = new FillRectRequest;
   fillrectrequest->size = size;
   fillrectrequest->color = color;
-  fillrectrequest->color.alpha
-      = (int) ((float) fillrectrequest->color.alpha 
-              * ((float) transform.alpha / 255.0));
+  fillrectrequest->color.alpha = color.alpha * transform.alpha;
   request.request_data = fillrectrequest;
 
   requests->push_back(request);
@@ -210,11 +209,11 @@ DrawingContext::draw_surface_part(DrawingRequest& request)
   SurfacePartRequest* surfacepartrequest
     = (SurfacePartRequest*) request.request_data;
 
-  surfacepartrequest->surface->impl->draw_part(
+  surfacepartrequest->surface->draw_part(
       surfacepartrequest->source.x, surfacepartrequest->source.y,
       request.pos.x, request.pos.y,
-      surfacepartrequest->size.x, surfacepartrequest->size.y, request.alpha,
-      request.drawing_effect);
+      surfacepartrequest->size.x, surfacepartrequest->size.y,
+      request.alpha, request.drawing_effect);
 
   delete surfacepartrequest;
 }
@@ -227,10 +226,10 @@ DrawingContext::draw_gradient(DrawingRequest& request)
   const Color& bottom = gradientrequest->bottom;
   
   glBegin(GL_QUADS);
-  glColor3ub(top.red, top.green, top.blue);
+  glColor4f(top.red, top.green, top.blue, top.alpha);
   glVertex2f(0, 0);
   glVertex2f(SCREEN_WIDTH, 0);
-  glColor3ub(bottom.red, bottom.green, bottom.blue);
+  glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
   glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
   glVertex2f(0, SCREEN_HEIGHT);
   glEnd();
@@ -259,18 +258,17 @@ DrawingContext::draw_filled_rect(DrawingRequest& request)
   float w = fillrectrequest->size.x;
   float h = fillrectrequest->size.y;
 
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  glColor4ub(fillrectrequest->color.red, fillrectrequest->color.green,
-             fillrectrequest->color.blue, fillrectrequest->color.alpha);
-  
-  glBegin(GL_POLYGON);
+  glDisable(GL_TEXTURE_2D);
+  glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
+            fillrectrequest->color.blue, fillrectrequest->color.alpha);
+  glBegin(GL_QUADS);
   glVertex2f(x, y);
   glVertex2f(x+w, y);
   glVertex2f(x+w, y+h);
   glVertex2f(x, y+h);
   glEnd();
-  glDisable(GL_BLEND);
+  glEnable(GL_TEXTURE_2D);
 
   delete fillrectrequest;
 }
@@ -296,14 +294,13 @@ DrawingContext::do_drawing()
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
 
-    glClearColor(1, 1, 1, 1);
+    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
     glClear(GL_COLOR_BUFFER_BIT);
     handle_drawing_requests(lightmap_requests);
     lightmap_requests.clear();
   
     glDisable(GL_BLEND);
-    glEnable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, lightmap->handle);
+    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, screen->h - lightmap_height, lightmap_width, lightmap_height);
 
     glViewport(0, 0, screen->w, screen->h);
@@ -312,6 +309,7 @@ DrawingContext::do_drawing()
     glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
     glMatrixMode(GL_MODELVIEW);    
     glLoadIdentity();
+    glEnable(GL_BLEND);
   }
 
   //glClear(GL_COLOR_BUFFER_BIT);
@@ -319,17 +317,9 @@ DrawingContext::do_drawing()
   drawing_requests.clear();
 
   if(use_lightmap) {
-    glEnable(GL_BLEND);
     glBlendFunc(GL_DST_COLOR, GL_ZERO);
-    //glDisable(GL_BLEND);
-    //glColor4f((float) rand() / (float) RAND_MAX, .22, .88, 1.0f);
-
-    glEnable(GL_TEXTURE_2D);
-    glDisable(GL_DEPTH_TEST);
-    glDisable(GL_CULL_FACE);
-    glDisable(GL_ALPHA_TEST);    
 
-    glBindTexture(GL_TEXTURE_2D, lightmap->handle);
+    glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
     glBegin(GL_QUADS);
 
     glTexCoord2f(0, lightmap_uv_bottom);
@@ -345,6 +335,8 @@ DrawingContext::do_drawing()
     glVertex2f(0, SCREEN_HEIGHT);
     
     glEnd();
+
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   }
 
   assert_gl("drawing");
@@ -363,13 +355,7 @@ DrawingContext::handle_drawing_requests(DrawingRequests& requests)
       case SURFACE:
       {
         const Surface* surface = (const Surface*) i->request_data;
-
-        if(i->zoom != 1.0)
-          surface->impl->draw_stretched(i->pos.x * i->zoom, i->pos.y * i->zoom,
-                         (int)(surface->w * i->zoom), (int)(surface->h * i->zoom),
-                         i->alpha, i->drawing_effect);
-        else
-          surface->impl->draw(i->pos.x, i->pos.y, i->alpha, i->drawing_effect);
+        surface->draw(i->pos.x, i->pos.y, i->alpha, i->drawing_effect);
         break;
       }
       case SURFACE_PART:
@@ -404,30 +390,24 @@ DrawingContext::pop_transform()
 }
 
 void
-DrawingContext::set_drawing_effect(uint32_t effect)
+DrawingContext::set_drawing_effect(DrawingEffect effect)
 {
   transform.drawing_effect = effect;
 }
 
-uint32_t
+DrawingEffect
 DrawingContext::get_drawing_effect() const
 {
   return transform.drawing_effect;
 }
 
 void
-DrawingContext::set_zooming(float zoom)
-{
-  transform.zoom = zoom;
-}
-
-void
-DrawingContext::set_alpha(uint8_t alpha)
+DrawingContext::set_alpha(float alpha)
 {
   transform.alpha = alpha;
 }
 
-uint8_t
+float
 DrawingContext::get_alpha() const
 {
   return transform.alpha;
index b3b6d28..dccd31b 100644 (file)
 #include <string>
 #include <stdint.h>
 
+#include <GL/gl.h>
 #include <SDL.h>
 #include <stdint.h>
 #include <memory>
 
 #include "math/vector.hpp"
-#include "video/screen.hpp"
-#include "video/surface.hpp"
-#include "video/font.hpp"
+#include "surface.hpp"
+#include "font.hpp"
+#include "color.hpp"
 
 class Surface;
 class Texture;
@@ -74,10 +75,10 @@ public:
   void draw_center_text(const Font* font, const std::string& text,
                         const Vector& position, int layer);
   /// Draws a color gradient onto the whole screen */
-  void draw_gradient(Color from, Color to, int layer);
+  void draw_gradient(const Color& from, const Color& to, int layer);
   /// Fills a rectangle.
   void draw_filled_rect(const Vector& topleft, const Vector& size,
-                        Color color, int layer);
+                        const Color& color, int layer);
   
   /// Processes all pending drawing requests and flushes the list.
   void do_drawing();
@@ -92,15 +93,13 @@ public:
   void pop_transform();
   
   /// Apply that effect in the next draws (effects are listed on surface.h).
-  void set_drawing_effect(uint32_t effect);
+  void set_drawing_effect(DrawingEffect effect);
   /// return currently applied drawing effect
-  uint32_t get_drawing_effect() const;
-  /// apply that zoom in the next draws */
-  void set_zooming(float zoom);
-  /// apply that alpha in the next draws */
-  void set_alpha(uint8_t alpha);
+  DrawingEffect get_drawing_effect() const;
+  /// apply that alpha in the next draws (1.0 means fully opaque) */
+  void set_alpha(float alpha);
   /// return currently set alpha
-  uint8_t get_alpha() const;
+  float get_alpha() const;
 
   enum Target {
     NORMAL, LIGHTMAP
@@ -114,12 +113,11 @@ private:
   {
   public:
     Vector translation;
-    uint32_t drawing_effect;
-    float zoom;
-    uint8_t alpha;
+    DrawingEffect drawing_effect;
+    float alpha;
     
     Transform()
-      : drawing_effect(NONE_EFFECT), zoom(1), alpha(255)
+      : drawing_effect(NO_EFFECT), alpha(1.0f)
     { }
     
     Vector apply(const Vector& v) const
@@ -182,9 +180,8 @@ private:
     Vector pos;                
     
     int layer;
-    uint32_t drawing_effect;
-    float zoom;
-    int alpha;
+    DrawingEffect drawing_effect;
+    float alpha;
     Blend blend;
     
     void* request_data;
@@ -212,7 +209,7 @@ private:
   SDL_Surface* screen;
   Target target;
   std::vector<Target> target_stack;
-  std::auto_ptr<Texture> lightmap;
+  Texture* lightmap;
   int lightmap_width, lightmap_height;
   float lightmap_uv_right, lightmap_uv_bottom;
 };
index 72c2ff4..c385576 100644 (file)
 #include "font.hpp"
 #include "drawing_context.hpp"
 
-Font::Font(const std::string& file, FontType ntype, int nw, int nh,
-        int nshadowsize)
-    : chars(0), shadow_chars(0), type(ntype), w(nw), h(nh),
-      shadowsize(nshadowsize)
+Font::Font(const std::string& file, const std::string& shadowfile,
+           int w, int h, int shadowsize)
+    : chars(0), shadow_chars(0), w(w), h(h), shadowsize(shadowsize)
 {
-  chars = new Surface(file, true);
+  chars = new Surface(file);
+  shadow_chars = new Surface(shadowfile);
  
-  switch(type) {
-    case TEXT:
-      first_char = 32;
-      break;
-    case NUM:
-      first_char = 48;
-      break;
-  }
-  char_count = (chars->h / h) * 16;
-   
-  // Load shadow font.
-  if(shadowsize > 0) {
-    SDL_Surface* conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
-    int pixels = conv->w * conv->h;
-    SDL_LockSurface(conv);
-    for(int i = 0; i < pixels; ++i) {
-      Uint32 *p = (Uint32 *)conv->pixels + i;
-      *p = *p & conv->format->Amask;
-    }
-    SDL_UnlockSurface(conv);
-    SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
-    shadow_chars = new Surface(conv, true);
-    SDL_FreeSurface(conv);
-  }
+  first_char = 32;
+  char_count = ((int) chars->get_height() / h) * 16;
 }
 
 Font::~Font()
@@ -118,7 +96,7 @@ Font::get_height() const
 
 void
 Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
-    uint32_t drawing_effect, uint8_t alpha) const
+           DrawingEffect drawing_effect, float alpha) const
 {
   /* Cut lines changes into seperate strings, needed to support center/right text
      alignments with break lines.
@@ -154,7 +132,7 @@ Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
 
 void
 Font::draw_text(const std::string& text, const Vector& pos, 
-    uint32_t drawing_effect, uint8_t alpha) const
+                DrawingEffect drawing_effect, float alpha) const
 {
   if(shadowsize > 0)
     draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
@@ -208,10 +186,8 @@ uint32_t decode_utf8(const std::string& text, size_t& p)
 
 void
 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
-                 uint32_t drawing_effect, uint8_t alpha) const
+                 DrawingEffect drawing_effect, float alpha) const
 {
-  SurfaceImpl* impl = pchars->impl;
-
   Vector p = pos;
   size_t i = 0;
   while(i < text.size()) {
@@ -250,7 +226,8 @@ Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
 
     int source_x = (font_index % 16) * w;
     int source_y = (font_index / 16) * h;
-    impl->draw_part(source_x, source_y, p.x, p.y, w, h, alpha, drawing_effect);
+    pchars->draw_part(source_x, source_y, p.x, p.y, w, h, alpha,
+                      drawing_effect);
     p.x += w;
   }
 }
index af6cd0b..6cace57 100644 (file)
@@ -35,13 +35,8 @@ enum FontAlignment {
 class Font
 {
 public:
-  enum FontType {
-    TEXT, // images for all characters
-    NUM   // only images for numbers
-  };
-  
-  Font(const std::string& file, FontType type, int w, int h,
-       int shadowsize=2);
+  Font(const std::string& file, const std::string& shadowfile,
+       int w, int h, int shadowsize = 2);
   ~Font();
   
   /** returns the width of a given text. (Note that I won't add a normal
@@ -63,20 +58,22 @@ public:
    * Type of alignment, drawing effect and alpha are optional. */
   void draw(const std::string& text, const Vector& pos,
             FontAlignment allignment = LEFT_ALLIGN,
-            uint32_t drawing_effect = NONE_EFFECT, uint8_t alpha = 255) const;
+            DrawingEffect drawing_effect = NO_EFFECT,
+            float alpha = 1.0f) const;
   
 private:
   friend class DrawingContext;
   
   void draw_text(const std::string& text, const Vector& pos,
-                 uint32_t drawing_effect = NONE_EFFECT, uint8_t alpha = 255) const;
+                 DrawingEffect drawing_effect = NO_EFFECT,
+                 float alpha = 1.0f) const;
   
   void draw_chars(Surface* pchars, const std::string& text,
-                  const Vector& position, uint32_t drawing_effect, uint8_t alpha) const;
+                  const Vector& position, DrawingEffect drawing_effect,
+                  float alpha) const;
   
   Surface* chars;
   Surface* shadow_chars;
-  FontType type;
   int w;
   int h;
   int shadowsize;
diff --git a/src/video/image_texture.cpp b/src/video/image_texture.cpp
new file mode 100644 (file)
index 0000000..2bd9af4
--- /dev/null
@@ -0,0 +1,19 @@
+#include <config.h>
+
+#include "image_texture.hpp"
+#include "texture_manager.hpp"
+
+ImageTexture::ImageTexture(SDL_Surface* surface)
+  : Texture(surface, GL_RGBA), refcount(0)
+{
+}
+
+ImageTexture::~ImageTexture()
+{
+}
+
+void
+ImageTexture::release()
+{
+  texture_manager->release(this);
+}
diff --git a/src/video/image_texture.hpp b/src/video/image_texture.hpp
new file mode 100644 (file)
index 0000000..9fe08af
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __SURFACE_TEXTURE_HPP__
+#define __SURFACE_TEXTURE_HPP__
+
+#include <string>
+#include "texture.hpp"
+
+class ImageTexture : public Texture
+{
+private:
+  std::string filename;
+  float image_width;
+  float image_height;
+  int refcount;
+
+public:
+  float get_image_width() const
+  {
+    return image_width;
+  }
+
+  float get_image_height() const
+  {
+    return image_height;
+  }
+  
+  float get_uv_right() const
+  {
+    return image_width / static_cast<float> (get_width());
+  }
+  
+  float get_uv_bottom() const
+  {
+    return image_height / static_cast<float> (get_height());
+  }
+
+  void ref()
+  {
+    refcount++;
+  }
+
+  void unref()
+  {
+    assert(refcount > 0);
+    refcount--;
+    if(refcount == 0)
+      release();
+  }
+
+private:
+  friend class TextureManager;
+  
+  ImageTexture(SDL_Surface* surface);
+  virtual ~ImageTexture();
+
+  void release();
+};
+
+#endif
+
index f7463f0..2227ccf 100644 (file)
 #include <unistd.h>
 
 #include <SDL.h>
-#include <SDL_image.h>
-
-#ifndef WIN32
-#include <sys/types.h>
-#include <ctype.h>
-#endif
 
 #include "gameconfig.hpp"
 #include "screen.hpp"
 #include "math/vector.hpp"
 
 static const float LOOP_DELAY = 20.0;
-extern SDL_Surface* screen;
-
-/* 'Stolen' from the SDL documentation.
- * Return the pixel value at (x, y)
- * NOTE: The surface must be locked before calling this!
- */
-Uint32 getpixel(SDL_Surface *surface, int x, int y)
-{
-    int bpp = surface->format->BytesPerPixel;
-    /* Here p is the address to the pixel we want to retrieve */
-    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
-
-    switch(bpp) {
-    case 1:
-        return *p;
-
-    case 2:
-        return *(Uint16 *)p;
-
-    case 3:
-        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
-            return p[0] << 16 | p[1] << 8 | p[2];
-        else
-            return p[0] | p[1] << 8 | p[2] << 16;
-
-    case 4:
-        return *(Uint32 *)p;
-
-    default:
-        return 0;       /* shouldn't happen, but avoids warnings */
-    }
-}
-
-/* 'Stolen' from the SDL documentation.
- * Set the pixel at (x, y) to the given value
- * NOTE: The surface must be locked before calling this!
- */
-void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
-{
-  int bpp = surface->format->BytesPerPixel;
-  /* Here p is the address to the pixel we want to set */
-  Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
-
-  switch(bpp) {
-    case 1:
-      *p = pixel;
-      break;
-
-    case 2:
-      *(Uint16 *)p = pixel;
-      break;
-
-    case 3:
-      if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
-        {
-          p[0] = (pixel >> 16) & 0xff;
-          p[1] = (pixel >> 8) & 0xff;
-          p[2] = pixel & 0xff;
-        }
-      else
-        {
-          p[0] = pixel & 0xff;
-          p[1] = (pixel >> 8) & 0xff;
-          p[2] = (pixel >> 16) & 0xff;
-        }
-      break;
-
-    case 4:
-      *(Uint32 *)p = pixel;
-      break;
-
-    default:
-      assert(false);
-  }
-}
-
-/* Draw a single pixel on the screen. */
-void drawpixel(int x, int y, Uint32 pixel)
-{
-  /* Lock the screen for direct access to the pixels */
-  if ( SDL_MUSTLOCK(screen) )
-    {
-      if ( SDL_LockSurface(screen) < 0 )
-        {
-          fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
-          return;
-        }
-    }
-
-  if(!(x < 0 || y < 0 || x > SCREEN_WIDTH || y > SCREEN_HEIGHT))
-    putpixel(screen, x, y, pixel);
-
-  if ( SDL_MUSTLOCK(screen) )
-    {
-      SDL_UnlockSurface(screen);
-    }
-  /* Update just the part of the display that we've changed */
-  SDL_UpdateRect(screen, x, y, 1, 1);
-}
-
-/* --- FILL A RECT --- */
 
 void fillrect(float x, float y, float w, float h, int r, int g, int b, int a)
 {
@@ -156,38 +49,18 @@ void fillrect(float x, float y, float w, float h, int r, int g, int b, int a)
     h = -h;
   }
 
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glColor4ub(r, g, b,a);
-  
+
+  glDisable(GL_TEXTURE_2D);
   glBegin(GL_POLYGON);
   glVertex2f(x, y);
   glVertex2f(x+w, y);
   glVertex2f(x+w, y+h);
   glVertex2f(x, y+h);
   glEnd();
-  glDisable(GL_BLEND);
-}
-
-/* Needed for line calculations */
-#define SGN(x) ((x)>0 ? 1 : ((x)==0 ? 0:(-1)))
-#define ABS(x) ((x)>0 ? (x) : (-x))
-
-void draw_line(float x1, float y1, float x2, float y2,
-                         int r, int g, int b, int a)
-{
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  glColor4ub(r, g, b,a);
-  
-  glBegin(GL_LINES);
-  glVertex2f(x1, y1);
-  glVertex2f(x2, y2);
-  glEnd();
-  glDisable(GL_BLEND);
+  glEnable(GL_TEXTURE_2D);
 }
 
-
 void fadeout(int fade_time)
 {
   float alpha_inc  = 256 / (fade_time / LOOP_DELAY);
@@ -196,9 +69,8 @@ void fadeout(int fade_time)
   while(alpha > 0) {
     alpha -= alpha_inc;
     fillrect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0,0,0, (int)alpha_inc);  // left side
-                                                   
-    DrawingContext context; // ugly...
-    context.do_drawing();
+    
+    SDL_GL_SwapBuffers();
     sound_manager->update();
     
     SDL_Delay(int(LOOP_DELAY));
@@ -227,8 +99,8 @@ void shrink_fade(const Vector& point, int fade_time)
     fillrect(SCREEN_WIDTH - right_cor, 0, right_cor, SCREEN_HEIGHT, 0,0,0);  // right side
     fillrect(0, 0, SCREEN_WIDTH, up_cor, 0,0,0);  // up side
     fillrect(0, SCREEN_HEIGHT - down_cor, SCREEN_WIDTH, down_cor+1, 0,0,0);  // down side                                                                                
-    DrawingContext context; // ugly...
-    context.do_drawing();
+
+    SDL_GL_SwapBuffers();
   
     sound_manager->update();
     SDL_Delay(int(LOOP_DELAY));
index 8f63498..a26d5e9 100644 (file)
 #include <vector>
 #include "math/vector.hpp"
 
-/** Stores 8bit RGBA values. */
-class Color
-{
-public:
-  Color()
-    : red(0), green(0), blue(0), alpha(255)
-  {}
-  
-  Color(Uint8 red_, Uint8 green_, Uint8 blue_, Uint8 alpha_ = 255)
-    : red(red_), green(green_), blue(blue_), alpha(alpha_)
-  {}
-  
-  Color(std::vector <unsigned int> color)
-    : red(0), green(0), blue(0), alpha(255)
-  { if(color.size() >= 3) { red = color[0]; green = color[1]; blue = color[2]; }
-  if(color.size() == 4) alpha = color[3]; }
-  
-  Color(std::vector <int> color)
-    : red(0), green(0), blue(0), alpha(255)
-  { if(color.size() >= 3) { red = color[0]; green = color[1]; blue = color[2]; }
-  if(color.size() == 4) alpha = color[3]; }
-  
-  Color(const Color& o)
-    : red(o.red), green(o.green), blue(o.blue), alpha(o.alpha)
-  { }
-  
-  bool operator==(const Color& o)
-  {
-    if(red == o.red && green == o.green &&
-       blue == o.blue && alpha == o.alpha)
-      return true;
-    return false;
-  }
-  
-  Uint32 map_rgb(SDL_Surface* surface)
-  { return SDL_MapRGB(surface->format, red, green, blue); }
-  Uint32 map_rgba(SDL_Surface* surface)
-  { return SDL_MapRGBA(surface->format, red, green, blue, alpha); }
-  
-  Uint8 red, green, blue, alpha;
-};
-
-Uint32 getpixel(SDL_Surface* surface, int x, int y);
-void putpixel(SDL_Surface* surface, int x, int y, Uint32 pixel);
-void drawpixel(int x, int y, Uint32 pixel);
 void fillrect(float x, float y, float w, float h, int r, int g, int b, int a = 255);
-void draw_line(float x1, float y1, float x2, float y2, int r, int g, int b, int a = 255);
 
 void fadeout(int fade_time);
 void shrink_fade(const Vector& point, int fade_time);
index 3121291..daca15c 100644 (file)
@@ -24,6 +24,7 @@
 #include <algorithm>
 #include <stdexcept>
 #include <sstream>
+#include <math.h>
 
 #include <SDL.h>
 #include <SDL_image.h>
 #include "physfs/physfs_sdl.hpp"
 #include "video/surface.hpp"
 #include "video/screen.hpp"
+#include "image_texture.hpp"
+#include "texture_manager.hpp"
 
-Surface::Surfaces Surface::surfaces;
-
-extern SDL_Surface* screen;
-
-SurfaceData::SurfaceData(SDL_Surface* temp, bool use_alpha_)
-    : type(SURFACE), surface(0), use_alpha(use_alpha_),
-      x(0), y(0), w(0), h(0)
+Surface::Surface(const std::string& file)
 {
-  // Copy the given surface and make sure that it is not stored in
-  // video memory
-  surface = SDL_CreateRGBSurface(temp->flags & (~SDL_HWSURFACE),
-                                 temp->w, temp->h,
-                                 temp->format->BitsPerPixel,
-                                 temp->format->Rmask,
-                                 temp->format->Gmask,
-                                 temp->format->Bmask,
-                                 temp->format->Amask);
-  if(!surface)
-    throw std::runtime_error("No memory left for surface");
-  
-  SDL_SetAlpha(temp,0,0);
-  SDL_BlitSurface(temp, NULL, surface, NULL);
-}
+  texture = texture_manager->get(file);
+  texture->ref();
+  uv_left = 0;
+  uv_top = 0;
+  uv_right = texture->get_uv_right();
+  uv_bottom = texture->get_uv_bottom();
 
-SurfaceData::SurfaceData(const std::string& file_, bool use_alpha_)
-    : type(LOAD), surface(0), file(file_), use_alpha(use_alpha_)
-{}
-
-SurfaceData::SurfaceData(const std::string& file_, int x_, int y_,
-    int w_, int h_, bool use_alpha_)
-    : type(LOAD_PART), surface(0), file(file_), use_alpha(use_alpha_),
-    x(x_), y(y_), w(w_), h(h_)
-{}
-
-SurfaceData::SurfaceData(Color top_gradient_, Color bottom_gradient_,
-    int w_, int h_)
-    : type(GRADIENT), surface(0), use_alpha(false), w(w_), h(h_)
-{
-  top_gradient = top_gradient_;
-  bottom_gradient = bottom_gradient_;
+  width = texture->get_image_width();
+  height = texture->get_image_height();
 }
 
-
-SurfaceData::~SurfaceData()
+Surface::Surface(const std::string& file, int x, int y, int w, int h)
 {
-  SDL_FreeSurface(surface);
-}
+  texture = texture_manager->get(file);
+  texture->ref();
 
-SurfaceImpl*
-SurfaceData::create()
-{
-  return create_SurfaceOpenGL();
-}
+  float tex_w = static_cast<float> (texture->get_width());
+  float tex_h = static_cast<float> (texture->get_height());
+  uv_left = static_cast<float>(x) / tex_w;
+  uv_top = static_cast<float>(y) / tex_h;
+  uv_right = static_cast<float>(x+w) / tex_w;
+  uv_bottom = static_cast<float>(y+h) / tex_h;
 
-SurfaceOpenGL*
-SurfaceData::create_SurfaceOpenGL()
-{
-  switch(type)
-  {
-    case LOAD:
-      return new SurfaceOpenGL(file);
-    case LOAD_PART:
-      return new SurfaceOpenGL(file, x, y, w, h);
-    case SURFACE:
-      return new SurfaceOpenGL(surface);
-    case GRADIENT:
-      return new SurfaceOpenGL(top_gradient, bottom_gradient, w, h);
-    default:
-      assert(false);
-  }
-}
-
-/* Quick utility function for texture creation */
-static int power_of_two(int input)
-{
-  int value = 1;
-
-  while ( value < input )
-  {
-    value <<= 1;
-  }
-  return value;
-}
-
-Surface::Surface(SDL_Surface* surf, bool use_alpha)
-    : impl(0), data(surf, use_alpha), w(0), h(0)
-{
-  impl = data.create();
-  if (impl)
-  {
-    w = impl->w;
-    h = impl->h;
-  }
-  surfaces.push_back(this);
-}
-
-Surface::Surface(const std::string& file, bool use_alpha)
-    : impl(0), data(file, use_alpha), w(0), h(0)
-{
-  impl = data.create();
-  if (impl)
-  {
-    w = impl->w;
-    h = impl->h;
-  }
-  surfaces.push_back(this);
+  width = w;
+  height = h;
 }
 
-Surface::Surface(const std::string& file, int x, int y, int w_, int h_, bool use_alpha)
-    : impl(0), data(file, x, y, w_, h_, use_alpha), w(0), h(0)
+Surface::Surface(const Surface& other)
 {
-  impl = data.create();
-  if (impl)
-  {
-    w = impl->w;
-    h = impl->h;
-  }
-  surfaces.push_back(this);
-}
+  texture = other.texture;
+  texture->ref();
 
-Surface::Surface(Color top_background, Color bottom_background, int w_, int h_)
-    : impl(0), data(top_background, bottom_background, w_, h_), w(0), h(0)
-{
-  impl = data.create();
-  if (impl)
-  {
-    w = impl->w;
-    h = impl->h;
-  }
-  surfaces.push_back(this);
+  uv_left = other.uv_left;
+  uv_top = other.uv_top;
+  uv_right = other.uv_right;
+  uv_bottom = other.uv_bottom;
+  width = other.width;
+  height = other.height;
 }
 
-void
-Surface::reload()
+const Surface&
+Surface::operator= (const Surface& other)
 {
-  delete impl;
-  impl = data.create();
-  if (impl)
-  {
-    w = impl->w;
-    h = impl->h;
-    for(std::vector<SurfaceData::Filter>::iterator i =
-        data.applied_filters.begin(); i != data.applied_filters.end();
-        i++)
-      impl->apply_filter(i->type, i->color);
-  }
-}
+  other.texture->ref();
+  texture->unref();
+  texture = other.texture;
 
-void Surface::apply_filter(int filter, Color color)
-{
-  impl->apply_filter(filter, color);
+  uv_left = other.uv_left;
+  uv_top = other.uv_top;
+  uv_right = other.uv_right;
+  uv_bottom = other.uv_bottom;
+  width = other.width;
+  height = other.height;
 
-  SurfaceData::Filter apply_filter;
-  apply_filter.type = filter;
-  apply_filter.color = color;
-  data.applied_filters.push_back(apply_filter);
+  return *this;
 }
 
 Surface::~Surface()
 {
-#ifdef DEBUG
-  bool found = false;
-  for(std::list<Surface*>::iterator i = surfaces.begin(); i != surfaces.end();
-      ++i)
-  {
-    if(*i == this)
-    {
-      found = true; break;
-    }
-  }
-  if(!found)
-    printf("Error: Surface freed twice!!!\n");
-#endif
-  surfaces.remove(this);
-  delete impl;
+  texture->unref();
 }
 
 void
-Surface::reload_all()
-{
-  for(Surfaces::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
-  {
-    (*i)->reload();
-  }
-}
-
-void
-Surface::debug_check()
-{
-  for(Surfaces::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
-  {
-    printf("Surface not freed: T:%d F:%s.\n", (*i)->data.type,
-           (*i)->data.file.c_str());
-  }
-}
-
-void
-apply_filter_to_surface(SDL_Surface* surface, int filter, Color color)
-{
-  if(filter == HORIZONTAL_FLIP_FILTER) {
-    SDL_Surface* sur_copy = sdl_surface_from_sdl_surface(surface);
-    SDL_BlitSurface(surface, NULL, sur_copy, NULL);
-    SDL_SetAlpha(sur_copy,0,0);
-
-    SDL_Rect src, dst;
-    src.y = dst.y = 0;
-    src.w = dst.w = 1;
-    src.h = dst.h = sur_copy->h;
-    for(int x = 0; x < sur_copy->w; x++)
-    {
-      src.x = x; dst.x = sur_copy->w-1 - x;
-      SDL_BlitSurface(sur_copy, &src, surface, &dst);
-    }
-
-    SDL_FreeSurface(sur_copy);
-  } else if(filter == MASK_FILTER) {
-    SDL_Surface* sur_copy = sdl_surface_from_sdl_surface(surface);
-
-    Uint8 r,g,b,a;
-
-    SDL_LockSurface(sur_copy);
-    for(int x = 0; x < sur_copy->w; x++)
-      for(int y = 0; y < sur_copy->h; y++) {
-        SDL_GetRGBA(getpixel(sur_copy,x,y), sur_copy->format, &r,&g,&b,&a);
-        if(a != 0) {
-          putpixel(sur_copy, x,y, color.map_rgba(sur_copy));
-        }
-      }
-    SDL_UnlockSurface(sur_copy);
-
-    SDL_BlitSurface(sur_copy, NULL, surface, NULL);
-    SDL_FreeSurface(sur_copy);
-  }
-}
-
-SDL_Surface*
-sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h)
-{
-  SDL_Rect src;
-  SDL_Surface * sdl_surface;
-  SDL_Surface * temp;
-  SDL_Surface * conv;
-
-  temp = IMG_Load_RW(get_physfs_SDLRWops(file), true);
-  if (temp == 0) {
-    std::stringstream msg;
-    msg << "Couldn't load '" << file << "': " << SDL_GetError();
-    throw std::runtime_error(msg.str());
-  }
-  
-  /* Set source rectangle for conv: */
-
-  src.x = x;
-  src.y = y;
-  src.w = w;
-  src.h = h;
-
-  conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, temp->format->BitsPerPixel,
-                              temp->format->Rmask,
-                              temp->format->Gmask,
-                              temp->format->Bmask,
-                              temp->format->Amask);
-
-  SDL_SetAlpha(temp,0,0);
-
-  SDL_BlitSurface(temp, &src, conv, NULL);
-  sdl_surface = SDL_DisplayFormatAlpha(conv);
-
-  if (sdl_surface == NULL) {
-    std::stringstream msg;
-    msg << "Can't convert file '" << file << "' to display format.";
-    throw std::runtime_error(msg.str());
-  }
-
-  SDL_FreeSurface(temp);
-  SDL_FreeSurface(conv);
-
-  return sdl_surface;
-}
-
-SDL_Surface*
-sdl_surface_from_file(const std::string& file)
-{
-  SDL_Surface* sdl_surface;
-  SDL_Surface* temp;
-
-  temp = IMG_Load_RW(get_physfs_SDLRWops(file), true);
-  if (temp == 0) {
-    std::stringstream msg;
-    msg << "Couldn't load file '" << file << "': " << SDL_GetError();
-    throw std::runtime_error(msg.str());
-  }
-
-  sdl_surface = SDL_DisplayFormatAlpha(temp);
-
-  if (sdl_surface == NULL) {
-    std::stringstream msg;
-    msg << "Couldn't convert file '" << file << "' to display format";
-    throw std::runtime_error(msg.str());
-  }
-
-  SDL_FreeSurface(temp);
-
-  return sdl_surface;
-}
-
-SDL_Surface*
-sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf)
+Surface::hflip()
 {
-  SDL_Surface* sdl_surface = SDL_DisplayFormatAlpha(sdl_surf);
-  if (sdl_surface == 0) {
-    std::stringstream msg;
-    msg << "Can't convert surface to display format.";
-    throw std::runtime_error(msg.str());
-  }
-
-  return sdl_surface;
+  std::swap(uv_left, uv_right);
 }
 
-SDL_Surface*
-sdl_surface_from_gradient(Color top, Color bottom, int w, int h)
+static inline void intern_draw(float left, float top, float right, float bottom,                               float uv_left, float uv_top,
+                               float uv_right, float uv_bottom,
+                               DrawingEffect effect)
 {
-  SDL_Surface* sdl_surface
-    = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
-                    screen->format->BitsPerPixel, screen->format->Rmask,
-                    screen->format->Gmask, screen->format->Bmask, 0);
-
-  if(sdl_surface == 0)
-    throw std::runtime_error("Can't create gradient surface");
-
-  if(top == bottom) {
-    SDL_FillRect(sdl_surface, NULL, SDL_MapRGB(sdl_surface->format,
-        top.red, top.green, top.blue));
-  } else {
-    float redstep = (float(bottom.red)-float(top.red)) / float(h);
-    float greenstep = (float(bottom.green)-float(top.green)) / float(h);
-    float bluestep = (float(bottom.blue) - float(top.blue)) / float(h);
-
-    SDL_Rect rect;
-    rect.x = 0;
-    rect.w = w;
-    rect.h = 1;
-    for(float y = 0; y < h; y++) {
-      rect.y = (int)y;
-      SDL_FillRect(sdl_surface, &rect, SDL_MapRGB(sdl_surface->format,
-            int(float(top.red) + redstep * y),
-            int(float(top.green) + greenstep * y),
-            int(float(top.blue) + bluestep * y)));
-    }
+  if(effect & HORIZONTAL_FLIP)
+    std::swap(uv_left, uv_right);
+  if(effect & VERTICAL_FLIP) {
+    std::swap(uv_top, uv_bottom);
   }
-
-  return sdl_surface;
-}
-
-//---------------------------------------------------------------------------
-
-SurfaceImpl::SurfaceImpl()
-  : sdl_surface(0)
-{}
-
-SurfaceImpl::~SurfaceImpl()
-{
-  if(sdl_surface != 0)
-    SDL_FreeSurface(sdl_surface);
-}
-
-SDL_Surface* SurfaceImpl::get_sdl_surface() const
-{
-  return sdl_surface;
-}
-
-SurfaceOpenGL::SurfaceOpenGL(SDL_Surface* surf)
-{
-  sdl_surface = sdl_surface_from_sdl_surface(surf);
-  create_gl(sdl_surface,&gl_texture);
-
-  w = sdl_surface->w;
-  h = sdl_surface->h;
-}
-
-SurfaceOpenGL::SurfaceOpenGL(const std::string& file)
-{
-  sdl_surface = sdl_surface_from_file(file);
-  create_gl(sdl_surface,&gl_texture);
-
-  w = sdl_surface->w;
-  h = sdl_surface->h;
-}
-
-SurfaceOpenGL::SurfaceOpenGL(const std::string& file_, int x_, int y_,
-    int w_, int h_)
-{
-  sdl_surface = sdl_surface_part_from_file(file_, x_, y_, w_, h_);
   
-  create_gl(sdl_surface, &gl_texture);
-  w = sdl_surface->w;
-  h = sdl_surface->h;  
-}
-
-SurfaceOpenGL::SurfaceOpenGL(Color top_gradient, Color bottom_gradient,
-    int _w, int _h)
-{
-  sdl_surface = sdl_surface_from_gradient(top_gradient, bottom_gradient,_w,_h);
-  create_gl(sdl_surface, &gl_texture);
-  w = sdl_surface->w;
-  h = sdl_surface->h;  
-}
-
-SurfaceOpenGL::~SurfaceOpenGL()
-{
-  glDeleteTextures(1, &gl_texture);
-}
-
-void
-SurfaceOpenGL::create_gl(SDL_Surface * surf, GLuint * tex)
-{
-  Uint32 saved_flags;
-  Uint8  saved_alpha;
-  int w, h;
-  SDL_Surface *conv;
-
-  w = power_of_two(surf->w);
-  h = power_of_two(surf->h),
-
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-      conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel,
-                                  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
-#else
-      conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel,
-                                  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
-#endif
-
-  /* Save the alpha blending attributes */
-  saved_flags = surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
-  saved_alpha = surf->format->alpha;
-  if ( (saved_flags & SDL_SRCALPHA)
-       == SDL_SRCALPHA )
-  {
-    SDL_SetAlpha(surf, 0, 0);
-  }
-
-  SDL_BlitSurface(surf, 0, conv, 0);
-
-  /* Restore the alpha blending attributes */
-  if ( (saved_flags & SDL_SRCALPHA)
-       == SDL_SRCALPHA )
-  {
-    SDL_SetAlpha(surf, saved_flags, saved_alpha);
-  }
-
-  // We check all the pixels of the surface to figure out which
-  // internal format OpenGL should use for storing it, ie. if no alpha
-  // is present store in RGB instead of RGBA, this saves a few bytes
-  // of memory, but much more importantly it makes the game look
-  // *much* better in 16bit color mode
-  int internal_format = GL_RGBA;
-  bool has_alpha = false;
-
-  unsigned char* buf = static_cast<unsigned char*>(conv->pixels);
-  for (int y = 0; y < surf->h; ++y)
-    for (int x = 0; x < surf->w; ++x)
-      {
-        if (buf[(conv->pitch*y + x*4) + 3] != 255)
-          {
-            has_alpha = true;
-            break;
-          }
-      }
-
-  if (!has_alpha)
-    {
-      internal_format = GL_RGB;
-    }
-
-  glGenTextures(1, &*tex);
-  glBindTexture(GL_TEXTURE_2D , *tex);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel);
-  glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels);
-  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-
-  SDL_FreeSurface(conv);
-}
-
-int
-SurfaceOpenGL::draw(float x, float y, Uint8 alpha, Uint32 effect)
-{
-  float pw = power_of_two(w);
-  float ph = power_of_two(h);
-
-  if(effect & SEMI_TRANSPARENT)
-    alpha = 128;
-
-  glEnable(GL_TEXTURE_2D);
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-  glColor4ub(alpha, alpha, alpha, alpha);
-
-  glBindTexture(GL_TEXTURE_2D, gl_texture);
-
-  glBegin(GL_QUADS);
-
-  if(effect & VERTICAL_FLIP & HORIZONTAL_FLIP)
-    {
-    glTexCoord2f(0, 0);
-    glVertex2f((float)w+x, (float)h+y);
-
-    glTexCoord2f((float)w / pw, 0);
-    glVertex2f(x, (float)h+y);
-
-    glTexCoord2f((float)w / pw, (float)h / ph);
-    glVertex2f(x, y);
-
-    glTexCoord2f(0, (float)h / ph);
-    glVertex2f((float)w+x, y);
-    }
-  else if(effect & VERTICAL_FLIP)
-    {
-    glTexCoord2f(0, 0);
-    glVertex2f(x, (float)h+y);
-
-    glTexCoord2f((float)w / pw, 0);
-    glVertex2f((float)w+x, (float)h+y);
-
-    glTexCoord2f((float)w / pw, (float)h / ph);
-    glVertex2f((float)w+x, y);
-    
-    glTexCoord2f(0, (float)h / ph);
-    glVertex2f(x, y);
-    }
-  else if(effect & HORIZONTAL_FLIP)
-    {
-    glTexCoord2f(0, 0);
-    glVertex2f((float)w+x, y);
-
-    glTexCoord2f((float)w / pw, 0);
-    glVertex2f(x, y);
-
-    glTexCoord2f((float)w / pw, (float)h / ph);
-    glVertex2f(x, (float)h+y);
-
-    glTexCoord2f(0, (float)h / ph);
-    glVertex2f((float)w+x, (float)h+y);
-    }
-  else
-    {
-    glTexCoord2f(0, 0);
-    glVertex2f(x, y);
-
-    glTexCoord2f((float)w / pw, 0);
-    glVertex2f((float)w+x, y);
-
-    glTexCoord2f((float)w / pw, (float)h / ph);
-    glVertex2f((float)w+x, (float)h+y);
-
-    glTexCoord2f(0, (float)h / ph);
-    glVertex2f(x, (float)h+y);
-    }
-  glEnd();
-
-  glDisable(GL_TEXTURE_2D);
-  glDisable(GL_BLEND);
-
-  return 0;
-}
-
-int
-SurfaceOpenGL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, Uint32 effect)
-{
-  float pw = power_of_two(int(this->w));
-  float ph = power_of_two(int(this->h));
-
-  if(effect & SEMI_TRANSPARENT)
-    alpha = 128;
-
-  glBindTexture(GL_TEXTURE_2D, gl_texture);
-
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-  glColor4ub(alpha, alpha, alpha, alpha);
-
-  glEnable(GL_TEXTURE_2D);
-
-
   glBegin(GL_QUADS);
+  glTexCoord2f(uv_left, uv_top);
+  glVertex2f(left, top);
+  
+  glTexCoord2f(uv_right, uv_top);
+  glVertex2f(right, top);
 
-  if(effect & VERTICAL_FLIP & HORIZONTAL_FLIP)
-    {
-    glTexCoord2f(sx / pw, (float)(sy+h) / ph);
-    glVertex2f((float)w+x, (float)h+y);
-
-    glTexCoord2f((sx+w) / pw, (sy+h) / ph);
-    glVertex2f(x, (float)h+y);
-
-    glTexCoord2f((float)(sx + w) / pw, sy / ph);
-    glVertex2f(x, y);
-
-    glTexCoord2f(sx / pw, sy / ph);
-    glVertex2f((float)w+x, y);
-    }
-  else if(effect & VERTICAL_FLIP)
-    {
-    glTexCoord2f(sx / pw, sy / ph);
-    glVertex2f(x, y);
-
-    glTexCoord2f((float)(sx + w) / pw, sy / ph);
-    glVertex2f(w+x, y);
-
-    glTexCoord2f((sx+w) / pw, (sy+h) / ph);
-    glVertex2f(w +x, h+y);
-
-    glTexCoord2f(sx / pw, (float)(sy+h) / ph);
-    glVertex2f(x, h+y);
-    }
-  else if(effect & HORIZONTAL_FLIP)
-    {
-    glTexCoord2f(sx / pw, sy / ph);
-    glVertex2f((float)w+x, y);
-
-    glTexCoord2f((float)(sx + w) / pw, sy / ph);
-    glVertex2f(x, y);
-
-    glTexCoord2f((sx+w) / pw, (sy+h) / ph);
-    glVertex2f(x, (float)h+y);
-
-    glTexCoord2f(sx / pw, (float)(sy+h) / ph);
-    glVertex2f((float)w+x, (float)h+y);
-    }
-  else
-    {
-    glTexCoord2f(sx / pw, (float)(sy+h) / ph);
-    glVertex2f(x, h+y);
-
-    glTexCoord2f((sx+w) / pw, (sy+h) / ph);
-    glVertex2f(w +x, h+y);
-
-    glTexCoord2f((float)(sx + w) / pw, sy / ph);
-    glVertex2f(w+x, y);
-
-    glTexCoord2f(sx / pw, sy / ph);
-    glVertex2f(x, y);
-    }
+  glTexCoord2f(uv_right, uv_bottom);
+  glVertex2f(right, bottom);
 
+  glTexCoord2f(uv_left, uv_bottom);
+  glVertex2f(left, bottom);
   glEnd();
-
-  glDisable(GL_TEXTURE_2D);
-  glDisable(GL_BLEND);
-
-  return 0;
 }
 
-int
-SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, Uint32 effect)
+void
+Surface::draw(float x, float y, float alpha, DrawingEffect effect) const
 {
-  float pw = power_of_two(sw);
-  float ph = power_of_two(sh);
+  glColor4f(1.0f, 1.0f, 1.0f, alpha);
+  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
 
-  if(effect & SEMI_TRANSPARENT)
-    alpha = 128;
-
-  glEnable(GL_TEXTURE_2D);
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-  glColor4ub(alpha, alpha, alpha, alpha);
-
-  glBindTexture(GL_TEXTURE_2D, gl_texture);
-
-  glBegin(GL_QUADS);
-
-  if(effect & VERTICAL_FLIP & HORIZONTAL_FLIP)
-    {
-    glTexCoord2f(0, 0);
-    glVertex2f((float)sw+x, (float)sh+y);
-
-    glTexCoord2f((float)w / pw, 0);
-    glVertex2f(x, (float)sh+y);
-
-    glTexCoord2f((float)w / pw, (float)h / ph);
-    glVertex2f(x, y);
-
-    glTexCoord2f(0, (float)h / ph);
-    glVertex2f((float)sw+x, y);
-    }
-  else if(effect & VERTICAL_FLIP)
-    {
-    glTexCoord2f(0, 0);
-    glVertex2f(x, (float)sh+y);
-
-    glTexCoord2f((float)w / pw, 0);
-    glVertex2f((float)sw+x, (float)sh+y);
-
-    glTexCoord2f((float)w / pw, (float)h / ph);
-    glVertex2f((float)sw+x, y);
-    
-    glTexCoord2f(0, (float)h / ph);
-    glVertex2f(x, y);
-    }
-  else if(effect & HORIZONTAL_FLIP)
-    {
-    glTexCoord2f(0, 0);
-    glVertex2f((float)sw+x, y);
-
-    glTexCoord2f((float)w / pw, 0);
-    glVertex2f(x, y);
-
-    glTexCoord2f((float)w / pw, (float)h / ph);
-    glVertex2f(x, (float)sh+y);
-
-    glTexCoord2f(0, (float)h / ph);
-    glVertex2f((float)sw+x, (float)sh+y);
-    }
-  else
-    {
-    glTexCoord2f(0, 0);
-    glVertex2f(x, y);
-
-    glTexCoord2f((float)w / pw, 0);
-    glVertex2f((float)sw+x, y);
-
-    glTexCoord2f((float)w / pw, (float)h / ph);
-    glVertex2f((float)sw+x, (float)sh+y);
-
-    glTexCoord2f(0, (float)h / ph);
-    glVertex2f(x, (float)sh+y);
-    }
-  glEnd();
-
-  glDisable(GL_TEXTURE_2D);
-  glDisable(GL_BLEND);
-
-  return 0;
+  intern_draw(x, y,
+              x + width, y + height,
+              uv_left, uv_top, uv_right, uv_bottom, effect);
 }
 
 void
-SurfaceOpenGL::apply_filter(int filter, Color color)
+Surface::draw_part(float src_x, float src_y, float dst_x, float dst_y,
+                   float width, float height, float alpha,
+                   DrawingEffect effect) const
 {
-  ::apply_filter_to_surface(sdl_surface, filter, color);
-  create_gl(sdl_surface,&gl_texture);
-
-  w = sdl_surface->w;
-  h = sdl_surface->h;
+  float uv_width = uv_right - uv_left;
+  float uv_height = uv_bottom - uv_top;
+  
+  float uv_left = this->uv_left + (uv_width * src_x) / this->width;
+  float uv_top = this->uv_top + (uv_height * src_y) / this->height;
+  float uv_right = this->uv_left + (uv_width * (src_x + width)) / this->width;
+  float uv_bottom = this->uv_top + (uv_height * (src_y + height)) / this->height;
+  
+  glColor4f(1.0f, 1.0f, 1.0f, alpha);
+  glBindTexture(GL_TEXTURE_2D, texture->get_handle());  
+  
+  intern_draw(dst_x, dst_y,
+              dst_x + width, dst_y + height,
+              uv_left, uv_top, uv_right, uv_bottom, effect);
 }
+
index bd0da7c..a5ba955 100644 (file)
@@ -1,7 +1,7 @@
-//  $Id: surface.h 2175 2004-11-24 19:02:49Z sik0fewl $
+//  $Id$
 // 
 //  SuperTux
-//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//  Copyright (C) 2005 Matthias Braun <matze@braunis.de>
 //
 //  This program is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU General Public License
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 //  02111-1307, USA.
-#ifndef SUPERTUX_TEXTURE_H
-#define SUPERTUX_TEXTURE_H
+#ifndef __SURFACE_HPP__
+#define __SURFACE_HPP__
 
 #include <string>
-#include <list>
 
-#include <SDL.h>
-#include <GL/gl.h>
+class ImageTexture;
 
-#include "math/vector.hpp"
-#include "video/screen.hpp"
-
-void apply_filter_to_surface(SDL_Surface *surface, int filter, int value);
-SDL_Surface* sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf);
-SDL_Surface* sdl_surface_from_nothing();
-
-class SurfaceImpl;
-class SurfaceOpenGL;
-class DrawingContext;
-  
 /// bitset for drawing effects
-enum {
+enum DrawingEffect {
   /** Don't apply anything */
-  NONE_EFFECT       = 0x0000,
+  NO_EFFECT       = 0x0000,
   /** Draw the Surface upside down */
   VERTICAL_FLIP     = 0x0001,
   /** Draw the Surface from left to down */
   HORIZONTAL_FLIP   = 0x0002,
-  /** Draw the Surface with alpha equal to 128 */
-  SEMI_TRANSPARENT  = 0x0004
-};
-
-/// types of filters
-enum {
-  HORIZONTAL_FLIP_FILTER,
-  MASK_FILTER,
-  NONE_FILTER
-};
-
-/** This class holds all the data necessary to construct a surface */
-class SurfaceData
-{
-public:
-  enum ConstructorType { LOAD, LOAD_PART, SURFACE, GRADIENT };
-  ConstructorType type;
-  SDL_Surface* surface;
-  std::string file;
-  
-  struct Filter { int type; Color color; };
-  std::vector<Filter> applied_filters;
-  
-  bool use_alpha;
-  int x;
-  int y;
-  int w;
-  int h;
-  Color top_gradient;
-  Color bottom_gradient;
-  
-  SurfaceData(SDL_Surface* surf, bool use_alpha_);
-  SurfaceData(const std::string& file_, bool use_alpha_);
-  SurfaceData(const std::string& file_, int x_, int y_, int w_, int h_, bool use_alpha_);
-  SurfaceData(Color top_gradient_, Color bottom_gradient_, int w_, int h_);
-  ~SurfaceData();
-  
-  SurfaceOpenGL* create_SurfaceOpenGL();
-  SurfaceImpl* create();
 };
 
-
-/** Container class that holds a surface, necessary so that we can
- *  switch Surface implementations (OpenGL, SDL) on the fly
+/**
+ * Container class that holds a surface, necessary so that we can
+ * reload Surface implementations on the fly
  */
 class Surface
 {
+private:
+  friend class DrawingContext;
+  friend class Font;
+  ImageTexture* texture;
+
+  float uv_left;
+  float uv_top;
+  float uv_right;
+  float uv_bottom;
+
+  void draw(float x, float y, float alpha, DrawingEffect effect) const;
+  void draw_part(float src_x, float src_y, float dst_x, float dst_y,
+                 float width, float height,
+                 float alpha, DrawingEffect effect) const;
+
+  float width;
+  float height;
 public:
-  SurfaceImpl* impl;
-  SurfaceData data;
-  int w;
-  int h;
-  
-  typedef std::list<Surface*> Surfaces;
-  static Surfaces surfaces;
-public:
-  static void reload_all();
-  static void debug_check();
-  
-  Surface(SDL_Surface* surf, bool use_alpha);
-  Surface(const std::string& file, bool use_alpha);
-  Surface(const std::string& file, int x, int y, int w, int h, bool use_alpha);
-  Surface(Color top_gradient, Color bottom_gradient, int w_, int h_);
+  Surface(const std::string& file);
+  Surface(const std::string& file, int x, int y, int w, int h);
+  Surface(const Surface& other);
   ~Surface();
+
+  /** flip the surface horizontally */
+  void hflip();
   
   /** Reload the surface, which is necesarry in case of a mode swich */
   void reload();
-  
-  void apply_filter(int filter, Color color = Color(0,0,0));
-};
 
-/** Surface implementation, all implementation have to inherit from
-    this class */
-class SurfaceImpl
-{
-protected:
-  SDL_Surface* sdl_surface;
-  
-public:
-  int w;
-  int h;
-  
-public:
-  SurfaceImpl();
-  virtual ~SurfaceImpl();
-  
-  /** Return 0 on success, -2 if surface needs to be reloaded */
-  virtual int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT) = 0;
-  virtual int draw_part(float sx, float sy, float x, float y, float w, float h,  Uint8 alpha, Uint32 effect = NONE_EFFECT) = 0;
-  virtual int draw_stretched(float x, float y, int w, int h, Uint8 alpha, Uint32 effect = NONE_EFFECT) = 0;
-  
-  
-  SDL_Surface* get_sdl_surface() const; // @evil@ try to avoid this function
-  
-  virtual void apply_filter(int filter, Color color = Color(0,0,0)) = 0;
-};
+  const Surface& operator= (const Surface& other);
 
-class SurfaceOpenGL : public SurfaceImpl
-{
-public:
-  GLuint gl_texture;
-  
-public:
-  SurfaceOpenGL(SDL_Surface* surf);
-  SurfaceOpenGL(const std::string& file);
-  SurfaceOpenGL(const std::string& file, int x, int y, int w, int h);
-  SurfaceOpenGL(Color top_gradient, Color bottom_gradient, int w, int h);
-  
-  virtual ~SurfaceOpenGL();
-  
-  int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT);
-  int draw_part(float sx, float sy, float x, float y, float w, float h,  Uint8 alpha, Uint32 effect = NONE_EFFECT);
-  int draw_stretched(float x, float y, int w, int h, Uint8 alpha, Uint32 effect = NONE_EFFECT);
-  
-  void apply_filter(int filter, Color color);
-  
-private:
-  void create_gl(SDL_Surface * surf, GLuint * tex);
+  float get_width() const
+  {
+    return width;
+  }
+
+  float get_height() const
+  {
+    return height;
+  }
 };
 
 #endif
index 98bfc91..a49a5cc 100644 (file)
@@ -96,12 +96,6 @@ Texture::~Texture()
   glDeleteTextures(1, &handle);
 }
 
-void upload_texture(SDL_Surface* , int , int , int , int , int , int )
-{
-  // TODO
-  assert(false);
-}
-
 void
 Texture::set_texture_params()
 {
@@ -109,7 +103,6 @@ Texture::set_texture_params()
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP);
 
   assert_gl("set texture params");
 }
index 8322e3c..3c8b4f7 100644 (file)
 #include <GL/gl.h>
 
 /**
- * This class is a very simple wrapper around a texture handle
+ * This class is a wrapper around a texture handle. It stores the texture width
+ * and height and provides convenience functions for uploading SDL_Surfaces
+ * into the texture
  */
 class Texture
 {
-public:
+protected:
+  friend class TextureManager;
   GLuint handle;
   unsigned int width;
   unsigned int height;
-  
+
+public:
   Texture(unsigned int width, unsigned int height, GLenum glformat);
   Texture(SDL_Surface* surface, GLenum glformat);
-  ~Texture();
+  virtual ~Texture();
+  
+  GLuint get_handle() const
+  {
+    return handle;
+  }
+
+  unsigned int get_width() const
+  {
+    return width;
+  }
+
+  unsigned int get_height() const
+  {
+    return height;
+  }
 
-  void upload_texture(SDL_Surface* image, int src_x, int src_y, int dst_x, int dst_y, 
-                      int width, int height);
 private:
   void set_texture_params();
 };
 
-
 #endif
 
diff --git a/src/video/texture_manager.cpp b/src/video/texture_manager.cpp
new file mode 100644 (file)
index 0000000..ab5788e
--- /dev/null
@@ -0,0 +1,218 @@
+#include <config.h>
+
+#include "texture_manager.hpp"
+
+#include <assert.h>
+#include <SDL.h>
+#include <SDL_image.h>
+#include <GL/gl.h>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include "physfs/physfs_sdl.hpp"
+#include "image_texture.hpp"
+#include "glutil.hpp"
+
+TextureManager* texture_manager = NULL;
+
+TextureManager::TextureManager()
+{
+}
+
+TextureManager::~TextureManager()
+{
+  for(ImageTextures::iterator i = image_textures.begin();
+      i != image_textures.end(); ++i) {
+    if(i->second == NULL)
+      continue;
+#ifdef DEBUG
+    std::cerr << "Warning: Texture '" << i->first << "' not freed\n";
+#endif
+    delete i->second;
+  }
+}
+
+ImageTexture*
+TextureManager::get(const std::string& filename)
+{
+  ImageTextures::iterator i = image_textures.find(filename);
+
+  ImageTexture* texture = NULL;
+  if(i != image_textures.end())
+    texture = i->second;
+
+  if(texture == NULL) {
+    texture = create_image_texture(filename);
+    image_textures[filename] = texture;
+  }
+
+  return texture;
+}
+
+void
+TextureManager::release(ImageTexture* texture)
+{
+  image_textures[texture->filename] = NULL;
+  delete texture;
+}
+
+void
+TextureManager::register_texture(Texture* texture)
+{
+  textures.insert(texture);
+}
+
+void
+TextureManager::remove_texture(Texture* texture)
+{
+  textures.erase(texture);
+}
+
+static inline int next_power_of_two(int val)
+{
+  int result = 1;
+  while(result < val)
+    result *= 2;
+  return result;
+}
+
+ImageTexture*
+TextureManager::create_image_texture(const std::string& filename)
+{
+  SDL_Surface* image = IMG_Load_RW(get_physfs_SDLRWops(filename), 1);
+  if(image == NULL) {
+    std::ostringstream msg;
+    msg << "Couldn't load image '" << filename << "' :" << SDL_GetError();
+    throw std::runtime_error(msg.str());
+  }
+
+  int texture_w = next_power_of_two(image->w);
+  int texture_h = next_power_of_two(image->h);
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+  SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE,
+      texture_w, texture_h, 32,
+      0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
+#else
+  SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE,
+      texture_w, texture_h, 32,
+      0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+#endif
+
+  if(convert == 0)
+    throw std::runtime_error("Couldn't create texture: out of memory");
+
+  SDL_SetAlpha(image, 0, 0);
+  SDL_BlitSurface(image, 0, convert, 0);
+
+  ImageTexture* result = NULL;
+  try {
+    result = new ImageTexture(convert);
+    result->filename = filename;
+    result->image_width = image->w;
+    result->image_height = image->h;
+  } catch(...) {
+    delete result;
+    SDL_FreeSurface(convert);
+    throw;
+  }
+  
+  SDL_FreeSurface(convert);
+  return result;
+}
+
+void
+TextureManager::save_textures()
+{
+  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+  glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
+  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
+  glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
+  glPixelStorei(GL_PACK_ALIGNMENT, 1);
+  for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) {
+    save_texture(*i);
+  }
+  for(ImageTextures::iterator i = image_textures.begin();
+      i != image_textures.end(); ++i) {
+    save_texture(i->second);
+  }
+}
+
+void
+TextureManager::save_texture(Texture* texture)
+{
+  SavedTexture saved_texture;
+  saved_texture.texture = texture;
+  glBindTexture(GL_TEXTURE_2D, texture->get_handle());
+  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
+                           &saved_texture.width);
+  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
+                           &saved_texture.height);
+  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER,
+                           &saved_texture.border);
+  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+                      &saved_texture.min_filter);
+  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+                      &saved_texture.mag_filter);
+  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+                      &saved_texture.wrap_s);
+  glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+                      &saved_texture.wrap_t);
+
+  size_t pixelssize = saved_texture.width * saved_texture.height * 4;
+  saved_texture.pixels = new char[pixelssize];
+  
+  glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                saved_texture.pixels);
+
+  saved_textures.push_back(saved_texture);
+
+  glDeleteTextures(1, &(texture->handle));
+  texture->handle = 0;
+
+  assert_gl("retrieving texture");
+}
+
+void
+TextureManager::reload_textures()
+{
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
+  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+  glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  
+  for(std::vector<SavedTexture>::iterator i = saved_textures.begin();
+      i != saved_textures.end(); ++i) {
+    SavedTexture& saved_texture = *i;
+    
+    GLuint handle;
+    glGenTextures(1, &handle);
+    assert_gl("creating texture handle");
+
+    glBindTexture(GL_TEXTURE_2D, handle);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+                 saved_texture.width, saved_texture.height,
+                 saved_texture.border, GL_RGBA,
+                 GL_UNSIGNED_BYTE, saved_texture.pixels);
+    delete[] saved_texture.pixels;
+    assert_gl("uploading texture pixel data");
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+                    saved_texture.min_filter);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+                    saved_texture.mag_filter);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+                    saved_texture.wrap_s);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+                    saved_texture.wrap_t);
+
+    assert_gl("setting texture_params");
+    saved_texture.texture->handle = handle;
+  }
+
+  saved_textures.clear();
+}
+
diff --git a/src/video/texture_manager.hpp b/src/video/texture_manager.hpp
new file mode 100644 (file)
index 0000000..0b0854f
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __IMAGE_TEXTURE_MANAGER_HPP__
+#define __IMAGE_TEXTURE_MANAGER_HPP__
+
+#include <GL/gl.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+
+class Texture;
+class ImageTexture;
+
+class TextureManager
+{
+public:
+  TextureManager();
+  ~TextureManager();
+
+  ImageTexture* get(const std::string& filename);
+  
+  void register_texture(Texture* texture);
+  void remove_texture(Texture* texture);
+
+  void save_textures();
+  void reload_textures();
+
+private:
+  friend class ImageTexture;
+  void release(ImageTexture* texture);
+  
+  typedef std::map<std::string, ImageTexture*> ImageTextures;
+  ImageTextures image_textures;
+
+  ImageTexture* create_image_texture(const std::string& filename);
+
+  typedef std::set<Texture*> Textures;
+  Textures textures;
+
+  struct SavedTexture
+  {
+    Texture* texture;
+    int width;
+    int height;
+    char* pixels;
+    int border;                              
+
+    int min_filter;
+    int mag_filter;
+    int wrap_s;
+    int wrap_t;
+  };
+  std::vector<SavedTexture> saved_textures;
+
+  void save_texture(Texture* texture);
+};
+
+extern TextureManager* texture_manager;
+
+#endif
+
index 45cc1bd..d731b4e 100644 (file)
@@ -352,8 +352,8 @@ WorldMap::WorldMap()
   tux = new Tux(this);
   add_object(tux);
     
-  messagedot = new Surface("images/worldmap/common/messagedot.png", true);
-  teleporterdot = new Surface("images/worldmap/common/teleporterdot.png", true);
+  messagedot = new Surface("images/worldmap/common/messagedot.png");
+  teleporterdot = new Surface("images/worldmap/common/teleporterdot.png");
 
   name = "<no title>";
   music = "salcon.ogg";