Initial sqlite3 maps.
[oweals/minetest.git] / src / tile.cpp
index 16140958f91fac22a5235a20a13c8360fc3aa571..c93c0680b42ca838a6c50264a21677a3e65b9d30 100644 (file)
@@ -1,6 +1,6 @@
 /*
 Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2010-2011 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 General Public License as published by
@@ -21,6 +21,12 @@ 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"
+
+/*
+       A cache from texture name to texture path
+*/
+MutexedMap<std::string, std::string> g_texturename_to_path_cache;
 
 /*
        Replaces the filename extension.
@@ -30,8 +36,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
                -> image = "a/image.jpg"
        Returns true on success.
 */
-inline bool replace_ext(std::string &path, const char *ext)
+static bool replace_ext(std::string &path, const char *ext)
 {
+       if(ext == NULL)
+               return false;
        // Find place of last dot, fail if \ or / found.
        s32 last_dot_i = -1;
        for(s32 i=path.size()-1; i>=0; i--)
@@ -59,7 +67,7 @@ inline bool replace_ext(std::string &path, const char *ext)
 
        If failed, return "".
 */
-inline std::string getImagePath(std::string path)
+static std::string getImagePath(std::string path)
 {
        // A NULL-ended list of possible image extensions
        const char *extensions[] = {
@@ -84,25 +92,55 @@ inline std::string getImagePath(std::string path)
 /*
        Gets the path to a texture by first checking if the texture exists
        in texture_path and if not, using the data path.
+
+       Checks all supported extensions by replacing the original extension.
+
+       If not found, returns "".
+
+       Utilizes a thread-safe cache.
 */
-inline std::string getTexturePath(std::string filename)
+std::string getTexturePath(const std::string &filename)
 {
+       std::string fullpath = "";
+       /*
+               Check from cache
+       */
+       bool incache = g_texturename_to_path_cache.get(filename, &fullpath);
+       if(incache)
+               return fullpath;
+       
+       /*
+               Check from texture_path
+       */
        std::string texture_path = g_settings.get("texture_path");
        if(texture_path != "")
        {
-               std::string fullpath = texture_path + '/' + filename;
-               // Check all filename extensions
-               fullpath = getImagePath(fullpath);
-               // If found, return it
-               if(fullpath != "")
-                       return fullpath;
+               std::string testpath = texture_path + '/' + filename;
+               // Check all filename extensions. Returns "" if not found.
+               fullpath = getImagePath(testpath);
        }
-       std::string fullpath = porting::getDataPath(filename.c_str());
-       // Check all filename extensions
-       fullpath = getImagePath(fullpath);
+       
+       /*
+               Check from default data directory
+       */
+       if(fullpath == "")
+       {
+               std::string testpath = porting::getDataPath(filename.c_str());
+               // Check all filename extensions. Returns "" if not found.
+               fullpath = getImagePath(testpath);
+       }
+       
+       // Add to cache (also an empty result is cached)
+       g_texturename_to_path_cache.set(filename, fullpath);
+       
+       // Finally return it
        return fullpath;
 }
 
+/*
+       TextureSource
+*/
+
 TextureSource::TextureSource(IrrlichtDevice *device):
                m_device(device),
                m_main_atlas_image(NULL),
@@ -141,7 +179,7 @@ void TextureSource::processQueue()
 
                dstream<<"INFO: TextureSource::processQueue(): "
                                <<"got texture request with "
-                               <<"name="<<request.key
+                               <<"name=\""<<request.key<<"\""
                                <<std::endl;
 
                GetResult<std::string, u32, u8, u8>
@@ -156,7 +194,7 @@ void TextureSource::processQueue()
 
 u32 TextureSource::getTextureId(const std::string &name)
 {
-       //dstream<<"INFO: getTextureId(): name="<<name<<std::endl;
+       //dstream<<"INFO: getTextureId(): \""<<name<<"\""<<std::endl;
 
        {
                /*
@@ -180,7 +218,7 @@ u32 TextureSource::getTextureId(const std::string &name)
        }
        else
        {
-               dstream<<"INFO: getTextureId(): Queued: name="<<name<<std::endl;
+               dstream<<"INFO: getTextureId(): Queued: name=\""<<name<<"\""<<std::endl;
 
                // We're gonna ask the result to be put into here
                ResultQueue<std::string, u32, u8, u8> result_queue;
@@ -188,8 +226,8 @@ u32 TextureSource::getTextureId(const std::string &name)
                // Throw a request in
                m_get_texture_queue.add(name, 0, 0, &result_queue);
                
-               dstream<<"INFO: Waiting for texture from main thread, name="
-                               <<name<<std::endl;
+               dstream<<"INFO: Waiting for texture from main thread, name=\""
+                               <<name<<"\""<<std::endl;
                
                try
                {
@@ -238,7 +276,7 @@ video::IImage* generate_image_from_scratch(std::string name,
 */
 u32 TextureSource::getTextureIdDirect(const std::string &name)
 {
-       dstream<<"INFO: getTextureIdDirect(): name="<<name<<std::endl;
+       //dstream<<"INFO: getTextureIdDirect(): name=\""<<name<<"\""<<std::endl;
 
        // Empty name means texture 0
        if(name == "")
@@ -267,14 +305,14 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
                n = m_name_to_id.find(name);
                if(n != NULL)
                {
-                       dstream<<"INFO: getTextureIdDirect(): name="<<name
-                                       <<" found in cache"<<std::endl;
+                       dstream<<"INFO: getTextureIdDirect(): \""<<name
+                                       <<"\" found in cache"<<std::endl;
                        return n->getValue();
                }
        }
 
-       dstream<<"INFO: getTextureIdDirect(): name="<<name
-                       <<" NOT found in cache. Creating it."<<std::endl;
+       dstream<<"INFO: getTextureIdDirect(): \""<<name
+                       <<"\" NOT found in cache. Creating it."<<std::endl;
        
        /*
                Get the base image
@@ -308,12 +346,13 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
        {
                // Construct base name
                base_image_name = name.substr(0, last_separator_position);
-               dstream<<"INFO: getTextureIdDirect(): Calling itself recursively"
-                               " to get base image, name="<<base_image_name<<std::endl;
+               /*dstream<<"INFO: getTextureIdDirect(): Calling itself recursively"
+                               " to get base image of \""<<name<<"\" = \""
+                <<base_image_name<<"\""<<std::endl;*/
                base_image_id = getTextureIdDirect(base_image_name);
        }
        
-       dstream<<"base_image_id="<<base_image_id<<std::endl;
+       //dstream<<"base_image_id="<<base_image_id<<std::endl;
        
        video::IVideoDriver* driver = m_device->getVideoDriver();
        assert(driver);
@@ -355,9 +394,9 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
                                        core::rect<s32>(pos_from, dim) // from
                        );
 
-                       dstream<<"INFO: getTextureIdDirect(): Loaded \""
+                       /*dstream<<"INFO: getTextureIdDirect(): Loaded \""
                                        <<base_image_name<<"\" from image cache"
-                                       <<std::endl;
+                                       <<std::endl;*/
                }
        }
        
@@ -367,7 +406,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
        */
 
        std::string last_part_of_name = name.substr(last_separator_position+1);
-       dstream<<"last_part_of_name="<<last_part_of_name<<std::endl;
+       //dstream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
 
        // Generate image according to part of name
        if(generate_image(last_part_of_name, baseimg, m_device) == false)
@@ -409,8 +448,8 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
        m_atlaspointer_cache.push_back(nap);
        m_name_to_id.insert(name, id);
 
-       dstream<<"INFO: getTextureIdDirect(): name="<<name
-                       <<": succesfully returning id="<<id<<std::endl;
+       /*dstream<<"INFO: getTextureIdDirect(): "
+                       <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;*/
        
        return id;
 }
@@ -456,7 +495,13 @@ void TextureSource::buildMainAtlas()
        core::dimension2d<u32> atlas_dim(1024,1024);
        video::IImage *atlas_img =
                        driver->createImage(video::ECF_A8R8G8B8, atlas_dim);
-       assert(atlas_img);
+       //assert(atlas_img);
+       if(atlas_img == NULL)
+       {
+               dstream<<"TextureSource::buildMainAtlas(): Failed to create atlas "
+                               "image; not building texture atlas."<<std::endl;
+               return;
+       }
 
        /*
                A list of stuff to add. This should contain as much of the
@@ -474,17 +519,19 @@ void TextureSource::buildMainAtlas()
        sourcelist.push_back("tree_top.png");
        sourcelist.push_back("water.png");
        sourcelist.push_back("leaves.png");
+       sourcelist.push_back("glass.png");
        sourcelist.push_back("mud.png^grass_side.png");
+       sourcelist.push_back("cobble.png");
+       sourcelist.push_back("mossycobble.png");
+       sourcelist.push_back("gravel.png");
+       sourcelist.push_back("cactus.png");
+       sourcelist.push_back("jungletree.png");
        
        sourcelist.push_back("stone.png^mineral_coal.png");
        sourcelist.push_back("stone.png^mineral_iron.png");
-       sourcelist.push_back("mud.png^mineral_coal.png");
-       sourcelist.push_back("mud.png^mineral_iron.png");
-       sourcelist.push_back("sand.png^mineral_coal.png");
-       sourcelist.push_back("sand.png^mineral_iron.png");
        
        // Padding to disallow texture bleeding
-       s32 padding = 8;
+       s32 padding = 16;
 
        /*
                First pass: generate almost everything
@@ -538,6 +585,9 @@ void TextureSource::buildMainAtlas()
                        break;
                }
                
+        dstream<<"INFO: TextureSource::buildMainAtlas(): Adding \""<<name
+                <<"\" to texture atlas"<<std::endl;
+
                // Tile it a few times in the X direction
                u16 xwise_tiling = 16;
                for(u32 j=0; j<xwise_tiling; j++)
@@ -628,8 +678,8 @@ void TextureSource::buildMainAtlas()
 video::IImage* generate_image_from_scratch(std::string name,
                IrrlichtDevice *device)
 {
-       dstream<<"INFO: generate_image_from_scratch(): "
-                       "name="<<name<<std::endl;
+       /*dstream<<"INFO: generate_image_from_scratch(): "
+                       "\""<<name<<"\""<<std::endl;*/
        
        video::IVideoDriver* driver = device->getVideoDriver();
        assert(driver);
@@ -666,8 +716,9 @@ video::IImage* generate_image_from_scratch(std::string name,
        {
                // Construct base name
                base_image_name = name.substr(0, last_separator_position);
-               dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively"
-                               " to get base image, name="<<base_image_name<<std::endl;
+               /*dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively"
+                               " to get base image of \""<<name<<"\" = \""
+                <<base_image_name<<"\""<<std::endl;*/
                baseimg = generate_image_from_scratch(base_image_name, device);
        }
        
@@ -677,7 +728,7 @@ video::IImage* generate_image_from_scratch(std::string name,
        */
 
        std::string last_part_of_name = name.substr(last_separator_position+1);
-       dstream<<"last_part_of_name="<<last_part_of_name<<std::endl;
+       //dstream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
        
        // Generate image according to part of name
        if(generate_image(last_part_of_name, baseimg, device) == false)
@@ -702,21 +753,21 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
        {
                // A normal texture; load it from a file
                std::string path = getTexturePath(part_of_name.c_str());
-               dstream<<"INFO: getTextureIdDirect(): Loading path \""<<path
-                               <<"\""<<std::endl;
+               /*dstream<<"INFO: generate_image(): Loading path \""<<path
+                               <<"\""<<std::endl;*/
                
                video::IImage *image = driver->createImageFromFile(path.c_str());
 
                if(image == NULL)
                {
-                       dstream<<"WARNING: Could not load image \""<<part_of_name
-                                       <<"\" from path \""<<path<<"\""
+                       dstream<<"WARNING: generate_image(): Could not load image \""
+                    <<part_of_name<<"\" from path \""<<path<<"\""
                                        <<" while building texture"<<std::endl;
 
                        //return false;
 
-                       dstream<<"WARNING: Creating a dummy"<<" image for \""
-                                       <<part_of_name<<"\""<<std::endl;
+                       dstream<<"WARNING: generate_image(): Creating a dummy"
+                    <<" image for \""<<part_of_name<<"\""<<std::endl;
 
                        // Just create a dummy image
                        //core::dimension2d<u32> dim(2,2);
@@ -740,7 +791,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                // If base image is NULL, load as base.
                if(baseimg == NULL)
                {
-                       dstream<<"INFO: Setting "<<part_of_name<<" as base"<<std::endl;
+                       //dstream<<"INFO: Setting "<<part_of_name<<" as base"<<std::endl;
                        /*
                                Copy it this way to get an alpha channel.
                                Otherwise images with alpha cannot be blitted on 
@@ -754,7 +805,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                // Else blit on base.
                else
                {
-                       dstream<<"INFO: Blitting "<<part_of_name<<" on base"<<std::endl;
+                       //dstream<<"INFO: Blitting "<<part_of_name<<" on base"<<std::endl;
                        // Size of the copied area
                        core::dimension2d<u32> dim = image->getDimension();
                        //core::dimension2d<u32> dim(16,16);
@@ -775,7 +826,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
        {
                // A special texture modification
 
-               dstream<<"INFO: getTextureIdDirect(): generating special "
+               dstream<<"INFO: generate_image(): generating special "
                                <<"modification \""<<part_of_name<<"\""
                                <<std::endl;
                
@@ -798,9 +849,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                {
                        if(baseimg == NULL)
                        {
-                               dstream<<"WARNING: getTextureIdDirect(): baseimg==NULL "
-                                               <<"for part_of_name="<<part_of_name
-                                               <<", cancelling."<<std::endl;
+                               dstream<<"WARNING: generate_image(): baseimg==NULL "
+                                               <<"for part_of_name=\""<<part_of_name
+                                               <<"\", cancelling."<<std::endl;
                                return false;
                        }
                        
@@ -935,9 +986,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                {
                        if(baseimg == NULL)
                        {
-                               dstream<<"WARNING: getTextureIdDirect(): baseimg==NULL "
-                                               <<"for part_of_name="<<part_of_name
-                                               <<", cancelling."<<std::endl;
+                               dstream<<"WARNING: generate_image(): baseimg==NULL "
+                                               <<"for part_of_name=\""<<part_of_name
+                                               <<"\", cancelling."<<std::endl;
                                return false;
                        }
 
@@ -955,9 +1006,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                {
                        if(baseimg != NULL)
                        {
-                               dstream<<"WARNING: getTextureIdDirect(): baseimg!=NULL "
-                                               <<"for part_of_name="<<part_of_name
-                                               <<", cancelling."<<std::endl;
+                               dstream<<"WARNING: generate_image(): baseimg!=NULL "
+                                               <<"for part_of_name=\""<<part_of_name
+                                               <<"\", cancelling."<<std::endl;
                                return false;
                        }
 
@@ -965,14 +1016,14 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
 
                        std::string path = getTexturePath(filename.c_str());
 
-                       dstream<<"INFO: getTextureIdDirect(): Loading path \""<<path
+                       dstream<<"INFO: generate_image(): Loading path \""<<path
                                        <<"\""<<std::endl;
                        
                        video::IImage *image = driver->createImageFromFile(path.c_str());
                        
                        if(image == NULL)
                        {
-                               dstream<<"WARNING: getTextureIdDirect(): Loading path \""
+                               dstream<<"WARNING: generate_image(): Loading path \""
                                                <<path<<"\" failed"<<std::endl;
                        }
                        else
@@ -1006,9 +1057,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                {
                        if(baseimg != NULL)
                        {
-                               dstream<<"WARNING: getTextureIdDirect(): baseimg!=NULL "
-                                               <<"for part_of_name="<<part_of_name
-                                               <<", cancelling."<<std::endl;
+                               dstream<<"WARNING: generate_image(): baseimg!=NULL "
+                                               <<"for part_of_name=\""<<part_of_name
+                                               <<"\", cancelling."<<std::endl;
                                return false;
                        }
 
@@ -1024,7 +1075,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
 
                        if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
                        {
-                               dstream<<"WARNING: getTextureIdDirect(): EVDF_RENDER_TO_TARGET"
+                               dstream<<"WARNING: generate_image(): EVDF_RENDER_TO_TARGET"
                                                " not supported. Creating fallback image"<<std::endl;
                                baseimg = generate_image_from_scratch(
                                                imagename_top, device);
@@ -1033,7 +1084,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        
                        u32 w0 = 64;
                        u32 h0 = 64;
-                       dstream<<"INFO: inventorycube w="<<w0<<" h="<<h0<<std::endl;
+                       //dstream<<"INFO: inventorycube w="<<w0<<" h="<<h0<<std::endl;
                        core::dimension2d<u32> dim(w0,h0);
                        
                        // Generate images for the faces of the cube
@@ -1098,6 +1149,8 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        /*scene::ILightSceneNode *light =*/ smgr->addLightSceneNode(0,
                                        v3f(-50, 100, 0), video::SColorf(0.5,0.5,0.5), 1000);
 
+                       smgr->setAmbientLight(video::SColorf(0.2,0.2,0.2));
+
                        // Render scene
                        driver->beginScene(true, true, video::SColor(0,0,0,0));
                        smgr->drawAll();
@@ -1133,7 +1186,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                }
                else
                {
-                       dstream<<"WARNING: getTextureIdDirect(): Invalid "
+                       dstream<<"WARNING: generate_image(): Invalid "
                                        " modification: \""<<part_of_name<<"\""<<std::endl;
                }
        }