]> git.lizzy.rs Git - minetest.git/blobdiff - src/tile.cpp
Translated using Weblate (German)
[minetest.git] / src / tile.cpp
index 92c56c2772d2098f1bdebecf6ec8027c065b17b3..aea9665f5eb69ca3568c12447538a81e7a1b8771 100644 (file)
@@ -1,6 +1,6 @@
 /*
-Minetest-c55
-Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
@@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "debug.h"
 #include "main.h" // for g_settings
 #include "filesys.h"
-#include "utility.h"
 #include "settings.h"
 #include "mesh.h"
 #include <ICameraSceneNode.h>
@@ -29,7 +28,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapnode.h" // For texture atlas making
 #include "nodedef.h" // For texture atlas making
 #include "gamedef.h"
-#include "utility_string.h"
+#include "util/string.h"
+#include "util/container.h"
+#include "util/thread.h"
+#include "util/numeric.h"
 
 /*
        A cache from texture name to texture path
@@ -204,10 +206,10 @@ class SourceImageCache
        {
                assert(img);
                // Remove old image
-               core::map<std::string, video::IImage*>::Node *n;
+               std::map<std::string, video::IImage*>::iterator n;
                n = m_images.find(name);
-               if(n){
-                       video::IImage *oldimg = n->getValue();
+               if(n != m_images.end()){
+                       video::IImage *oldimg = n->second;
                        if(oldimg)
                                oldimg->drop();
                }
@@ -227,20 +229,20 @@ class SourceImageCache
        }
        video::IImage* get(const std::string &name)
        {
-               core::map<std::string, video::IImage*>::Node *n;
+               std::map<std::string, video::IImage*>::iterator n;
                n = m_images.find(name);
-               if(n)
-                       return n->getValue();
+               if(n != m_images.end())
+                       return n->second;
                return NULL;
        }
        // Primarily fetches from cache, secondarily tries to read from filesystem
        video::IImage* getOrLoad(const std::string &name, IrrlichtDevice *device)
        {
-               core::map<std::string, video::IImage*>::Node *n;
+               std::map<std::string, video::IImage*>::iterator n;
                n = m_images.find(name);
-               if(n){
-                       n->getValue()->grab(); // Grab for caller
-                       return n->getValue();
+               if(n != m_images.end()){
+                       n->second->grab(); // Grab for caller
+                       return n->second;
                }
                video::IVideoDriver* driver = device->getVideoDriver();
                std::string path = getTexturePath(name.c_str());
@@ -261,7 +263,7 @@ class SourceImageCache
                return img;
        }
 private:
-       core::map<std::string, video::IImage*> m_images;
+       std::map<std::string, video::IImage*> m_images;
 };
 
 /*
@@ -370,6 +372,18 @@ class TextureSource : public IWritableTextureSource
        // Update new texture pointer and texture coordinates to an
        // AtlasPointer based on it's texture id
        void updateAP(AtlasPointer &ap);
+       bool isKnownSourceImage(const std::string &name)
+       {
+               bool is_known = false;
+               bool cache_found = m_source_image_existence.get(name, &is_known);
+               if(cache_found)
+                       return is_known;
+               // Not found in cache; find out if a local file exists
+               is_known = (getTexturePath(name) != "");
+               m_source_image_existence.set(name, is_known);
+               return is_known;
+       }
 
        // Processes queued texture requests from other threads.
        // Shall be called from the main thread.
@@ -398,11 +412,14 @@ class TextureSource : public IWritableTextureSource
        // This should be only accessed from the main thread
        SourceImageCache m_sourcecache;
 
+       // Thread-safe cache of what source images are known (true = known)
+       MutexedMap<std::string, bool> m_source_image_existence;
+
        // A texture id is index in this array.
        // The first position contains a NULL texture.
-       core::array<SourceAtlasPointer> m_atlaspointer_cache;
+       std::vector<SourceAtlasPointer> m_atlaspointer_cache;
        // Maps a texture name to an index in the former.
-       core::map<std::string, u32> m_name_to_id;
+       std::map<std::string, u32> m_name_to_id;
        // The two former containers are behind this mutex
        JMutex m_atlaspointer_cache_mutex;
        
@@ -448,11 +465,11 @@ u32 TextureSource::getTextureId(const std::string &name)
                        See if texture already exists
                */
                JMutexAutoLock lock(m_atlaspointer_cache_mutex);
-               core::map<std::string, u32>::Node *n;
+               std::map<std::string, u32>::iterator n;
                n = m_name_to_id.find(name);
-               if(n != NULL)
+               if(n != m_name_to_id.end())
                {
-                       return n->getValue();
+                       return n->second;
                }
        }
        
@@ -502,6 +519,11 @@ u32 TextureSource::getTextureId(const std::string &name)
 // Overlay image on top of another image (used for cracks)
 void overlay(video::IImage *image, video::IImage *overlay);
 
+// Draw an image on top of an another one, using the alpha channel of the
+// source image
+static void blit_with_alpha(video::IImage *src, video::IImage *dst,
+               v2s32 src_pos, v2s32 dst_pos, v2u32 size);
+
 // Brighten image
 void brighten(video::IImage *image);
 // Parse a transform name
@@ -557,13 +579,13 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
        {
                JMutexAutoLock lock(m_atlaspointer_cache_mutex);
 
-               core::map<std::string, u32>::Node *n;
+               std::map<std::string, u32>::iterator n;
                n = m_name_to_id.find(name);
-               if(n != NULL)
+               if(n != m_name_to_id.end())
                {
                        /*infostream<<"getTextureIdDirect(): \""<<name
                                        <<"\" found in cache"<<std::endl;*/
-                       return n->getValue();
+                       return n->second;
                }
        }
 
@@ -702,7 +724,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
                baseimg_dim = baseimg->getDimension();
        SourceAtlasPointer nap(name, ap, baseimg, v2s32(0,0), baseimg_dim);
        m_atlaspointer_cache.push_back(nap);
-       m_name_to_id.insert(name, id);
+       m_name_to_id[name] = id;
 
        /*infostream<<"getTextureIdDirect(): "
                        <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;*/
@@ -747,7 +769,7 @@ void TextureSource::processQueue()
        /*
                Fetch textures
        */
-       if(m_get_texture_queue.size() > 0)
+       if(!m_get_texture_queue.empty())
        {
                GetRequest<std::string, u32, u8, u8>
                                request = m_get_texture_queue.pop();
@@ -774,6 +796,7 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im
        assert(get_current_thread_id() == m_main_thread);
        
        m_sourcecache.insert(name, img, true, m_device->getVideoDriver());
+       m_source_image_existence.set(name, true);
 }
        
 void TextureSource::rebuildImagesAndTextures()
@@ -849,7 +872,7 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
                main content features
        */
 
-       core::map<std::string, bool> sourcelist;
+       std::set<std::string> sourcelist;
 
        for(u16 j=0; j<MAX_CONTENT+1; j++)
        {
@@ -859,16 +882,16 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
                for(u32 i=0; i<6; i++)
                {
                        std::string name = f.tiledef[i].name;
-                       sourcelist[name] = true;
+                       sourcelist.insert(name);
                }
        }
        
        infostream<<"Creating texture atlas out of textures: ";
-       for(core::map<std::string, bool>::Iterator
-                       i = sourcelist.getIterator();
-                       i.atEnd() == false; i++)
+       for(std::set<std::string>::iterator
+                       i = sourcelist.begin();
+                       i != sourcelist.end(); ++i)
        {
-               std::string name = i.getNode()->getKey();
+               std::string name = *i;
                infostream<<"\""<<name<<"\" ";
        }
        infostream<<std::endl;
@@ -887,11 +910,11 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
        pos_in_atlas.X = column_padding;
        pos_in_atlas.Y = padding;
 
-       for(core::map<std::string, bool>::Iterator
-                       i = sourcelist.getIterator();
-                       i.atEnd() == false; i++)
+       for(std::set<std::string>::iterator
+                       i = sourcelist.begin();
+                       i != sourcelist.end(); ++i)
        {
-               std::string name = i.getNode()->getKey();
+               std::string name = *i;
 
                // Generate image by name
                video::IImage *img2 = generate_image_from_scratch(name, m_device,
@@ -1003,11 +1026,11 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
                bool reuse_old_id = false;
                u32 id = m_atlaspointer_cache.size();
                // Check old id without fetching a texture
-               core::map<std::string, u32>::Node *n;
+               std::map<std::string, u32>::iterator n;
                n = m_name_to_id.find(name);
                // If it exists, we will replace the old definition
-               if(n){
-                       id = n->getValue();
+               if(n != m_name_to_id.end()){
+                       id = n->second;
                        reuse_old_id = true;
                        /*infostream<<"TextureSource::buildMainAtlas(): "
                                        <<"Replacing old AtlasPointer"<<std::endl;*/
@@ -1043,12 +1066,12 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
        /*
                Second pass: set texture pointer in generated AtlasPointers
        */
-       for(core::map<std::string, bool>::Iterator
-                       i = sourcelist.getIterator();
-                       i.atEnd() == false; i++)
+       for(std::set<std::string>::iterator
+                       i = sourcelist.begin();
+                       i != sourcelist.end(); ++i)
        {
-               std::string name = i.getNode()->getKey();
-               if(m_name_to_id.find(name) == NULL)
+               std::string name = *i;
+               if(m_name_to_id.find(name) == m_name_to_id.end())
                        continue;
                u32 id = m_name_to_id[name];
                //infostream<<"id of name "<<name<<" is "<<id<<std::endl;
@@ -1193,10 +1216,11 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        // Position to copy the blitted from in the blitted image
                        core::position2d<s32> pos_from(0,0);
                        // Blit
-                       image->copyToWithAlpha(baseimg, pos_to,
+                       /*image->copyToWithAlpha(baseimg, pos_to,
                                        core::rect<s32>(pos_from, dim),
                                        video::SColor(255,255,255,255),
-                                       NULL);
+                                       NULL);*/
+                       blit_with_alpha(image, baseimg, pos_from, pos_to, dim);
                        // Drop image
                        image->drop();
                }
@@ -1266,7 +1290,8 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                                It is an image with a number of cracking stages
                                horizontally tiled.
                        */
-                       video::IImage *img_crack = sourcecache->getOrLoad("crack.png", device);
+                       video::IImage *img_crack = sourcecache->getOrLoad(
+                                       "crack_anylength.png", device);
                
                        if(img_crack && progression >= 0)
                        {
@@ -1305,11 +1330,13 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                                        }
                                        else
                                        {
-                                               img_crack_scaled->copyToWithAlpha(
+                                               /*img_crack_scaled->copyToWithAlpha(
                                                                baseimg,
                                                                v2s32(0,0),
                                                                core::rect<s32>(v2s32(0,0), dim_base),
-                                                               video::SColor(255,255,255,255));
+                                                               video::SColor(255,255,255,255));*/
+                                               blit_with_alpha(img_crack_scaled, baseimg,
+                                                               v2s32(0,0), v2s32(0,0), dim_base);
                                        }
                                }
 
@@ -1334,7 +1361,11 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        u32 h0 = stoi(sf.next(":"));
                        infostream<<"combined w="<<w0<<" h="<<h0<<std::endl;
                        core::dimension2d<u32> dim(w0,h0);
-                       baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
+                       if(baseimg == NULL)
+                       {
+                               baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
+                               baseimg->fill(video::SColor(0,0,0,0));
+                       }
                        while(sf.atend() == false)
                        {
                                u32 x = stoi(sf.next(","));
@@ -1354,10 +1385,11 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                                                        driver->createImage(video::ECF_A8R8G8B8, dim);
                                        img->copyTo(img2);
                                        img->drop();
-                                       img2->copyToWithAlpha(baseimg, pos_base,
+                                       /*img2->copyToWithAlpha(baseimg, pos_base,
                                                        core::rect<s32>(v2s32(0,0), dim),
                                                        video::SColor(255,255,255,255),
-                                                       NULL);
+                                                       NULL);*/
+                                       blit_with_alpha(img2, baseimg, v2s32(0,0), pos_base, dim);
                                        img2->drop();
                                }
                                else
@@ -1669,6 +1701,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                                return false;
                        }
 
+                       // Fill target image with transparency
+                       img->fill(video::SColor(0,0,0,0));
+
                        core::dimension2d<u32> dim = frame_size;
                        core::position2d<s32> pos_dst(0, 0);
                        core::position2d<s32> pos_src(0, frame_index * frame_size.Y);
@@ -1721,6 +1756,30 @@ void overlay(video::IImage *image, video::IImage *overlay)
        }
 }
 
+/*
+       Draw an image on top of an another one, using the alpha channel of the
+       source image
+
+       This exists because IImage::copyToWithAlpha() doesn't seem to always
+       work.
+*/
+static void blit_with_alpha(video::IImage *src, video::IImage *dst,
+               v2s32 src_pos, v2s32 dst_pos, v2u32 size)
+{
+       for(u32 y0=0; y0<size.Y; y0++)
+       for(u32 x0=0; x0<size.X; x0++)
+       {
+               s32 src_x = src_pos.X + x0;
+               s32 src_y = src_pos.Y + y0;
+               s32 dst_x = dst_pos.X + x0;
+               s32 dst_y = dst_pos.Y + y0;
+               video::SColor src_c = src->getPixel(src_x, src_y);
+               video::SColor dst_c = dst->getPixel(dst_x, dst_y);
+               dst_c = src_c.getInterpolated(dst_c, (float)src_c.getAlpha()/255.0f);
+               dst->setPixel(dst_x, dst_y, dst_c);
+       }
+}
+
 void brighten(video::IImage *image)
 {
        if(image == NULL)