Properly update textures in node definitions
authorPerttu Ahola <celeron55@gmail.com>
Tue, 15 Nov 2011 11:13:18 +0000 (13:13 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Tue, 29 Nov 2011 17:13:43 +0000 (19:13 +0200)
src/client.cpp
src/client.h
src/game.cpp
src/nodedef.cpp
src/nodedef.h
src/tile.cpp
src/tile.h

index c89273a800f90a652aa5039359ab5966d30992d1..7093a5190a2c40d176bf8279bb1437c2ba9cdba5 100644 (file)
@@ -222,16 +222,14 @@ Client::Client(
 
        // Build main texture atlas, now that the GameDef exists (that is, us)
        if(g_settings->getBool("enable_texture_atlas"))
-               tsrc->buildMainAtlas(this);
+               m_tsrc->buildMainAtlas(this);
        else
                infostream<<"Not building texture atlas."<<std::endl;
        
-       // Update textures
-       m_nodedef->updateTextures(tsrc);
+       // Update node textures
+       m_nodedef->updateTextures(m_tsrc);
 
-       // NOTE: This should be done only after getting possible dynamic
-       // game definitions from the server, or at least shut down and
-       // restarted when doing so
+       // Start threads after setting up content definitions
        m_mesh_update_thread.Start();
 
        /*
@@ -1568,17 +1566,28 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                                rfile->drop();
                                continue;
                        }
-                       m_tsrc->insertImage(name, img);
+                       m_tsrc->insertSourceImage(name, img);
+                       img->drop();
                        rfile->drop();
                }
+               
+               // Rebuild inherited images and recreate textures
+               m_tsrc->rebuildImagesAndTextures();
 
                // Update texture atlas
                if(g_settings->getBool("enable_texture_atlas"))
                        m_tsrc->buildMainAtlas(this);
                
+               // Update node textures
+               m_nodedef->updateTextures(m_tsrc);
+
                // Resume threads
                m_mesh_update_thread.setRun(true);
                m_mesh_update_thread.Start();
+
+               ClientEvent event;
+               event.type = CE_TEXTURES_UPDATED;
+               m_client_event_queue.push_back(event);
        }
        else
        {
index abbbed2f8d50b44b2e6b20bf0c01677b7835774e..148acc0721d08b0fd543fcd2d2351a1cc9ff094c 100644 (file)
@@ -122,6 +122,7 @@ enum ClientEventType
        CE_PLAYER_DAMAGE,
        CE_PLAYER_FORCE_MOVE,
        CE_DEATHSCREEN,
+       CE_TEXTURES_UPDATED
 };
 
 struct ClientEvent
@@ -143,6 +144,8 @@ struct ClientEvent
                        f32 camera_point_target_y;
                        f32 camera_point_target_z;
                } deathscreen;
+               struct{
+               } textures_updated;
        };
 };
 
@@ -302,15 +305,11 @@ public:
        ClientEvent getClientEvent();
        
        inline bool accessDenied()
-       {
-               return m_access_denied;
-       }
+       { return m_access_denied; }
 
        inline std::wstring accessDeniedReason()
-       {
-               return m_access_denied_reason;
-       }
-
+       { return m_access_denied_reason; }
+       
        float getRTT(void);
 
        // IGameDef interface
index fc87deb296bedeefff5030404eb1e883bc639de1..a8525a04c55b2614be8bec8aa203d1e83373650a 100644 (file)
@@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "content_mapnode.h" // For content_mapnode_init
 #include "tooldef.h"
 #include "content_mapnode.h" // Default nodes
+#include "tile.h" // For TextureSource
 
 /*
        Setting this to 1 enables a special camera mode that forces
@@ -519,7 +520,7 @@ void getPointedNode(Client *client, v3f player_position,
        } // for coords
 }
 
-void update_skybox(video::IVideoDriver* driver,
+void update_skybox(video::IVideoDriver* driver, ITextureSource *tsrc,
                scene::ISceneManager* smgr, scene::ISceneNode* &skybox,
                float brightness)
 {
@@ -535,32 +536,32 @@ void update_skybox(video::IVideoDriver* driver,
        if(brightness >= 0.5)
        {
                skybox = smgr->addSkyBoxSceneNode(
-                       driver->getTexture(getTexturePath("skybox2.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox3.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1.png").c_str()));
+                       tsrc->getTextureRaw("skybox2.png"),
+                       tsrc->getTextureRaw("skybox3.png"),
+                       tsrc->getTextureRaw("skybox1.png"),
+                       tsrc->getTextureRaw("skybox1.png"),
+                       tsrc->getTextureRaw("skybox1.png"),
+                       tsrc->getTextureRaw("skybox1.png"));
        }
        else if(brightness >= 0.2)
        {
                skybox = smgr->addSkyBoxSceneNode(
-                       driver->getTexture(getTexturePath("skybox2_dawn.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox3_dawn.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1_dawn.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1_dawn.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1_dawn.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1_dawn.png").c_str()));
+                       tsrc->getTextureRaw("skybox2_dawn.png"),
+                       tsrc->getTextureRaw("skybox3_dawn.png"),
+                       tsrc->getTextureRaw("skybox1_dawn.png"),
+                       tsrc->getTextureRaw("skybox1_dawn.png"),
+                       tsrc->getTextureRaw("skybox1_dawn.png"),
+                       tsrc->getTextureRaw("skybox1_dawn.png"));
        }
        else
        {
                skybox = smgr->addSkyBoxSceneNode(
-                       driver->getTexture(getTexturePath("skybox2_night.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox3_night.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1_night.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1_night.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1_night.png").c_str()),
-                       driver->getTexture(getTexturePath("skybox1_night.png").c_str()));
+                       tsrc->getTextureRaw("skybox2_night.png"),
+                       tsrc->getTextureRaw("skybox3_night.png"),
+                       tsrc->getTextureRaw("skybox1_night.png"),
+                       tsrc->getTextureRaw("skybox1_night.png"),
+                       tsrc->getTextureRaw("skybox1_night.png"),
+                       tsrc->getTextureRaw("skybox1_night.png"));
        }
 }
 
@@ -771,7 +772,7 @@ void the_game(
        */
        float old_brightness = 1.0;
        scene::ISceneNode* skybox = NULL;
-       update_skybox(driver, smgr, skybox, 1.0);
+       update_skybox(driver, tsrc, smgr, skybox, 1.0);
        
        /*
                Create the camera node
@@ -886,6 +887,8 @@ void the_game(
        // A test
        //throw con::PeerNotFoundException("lol");
 
+       float brightness = 1.0;
+
        core::list<float> frametime_log;
 
        float nodig_delay_counter = 0.0;
@@ -1537,6 +1540,10 @@ void the_game(
                                        player->setPosition(player->getPosition() + v3f(0,-BS,0));
                                        camera.update(player, busytime, screensize);*/
                                }
+                               else if(event.type == CE_TEXTURES_UPDATED)
+                               {
+                                       update_skybox(driver, tsrc, smgr, skybox, brightness);
+                               }
                        }
                }
                
@@ -1902,25 +1909,27 @@ void the_game(
                /*
                        Calculate stuff for drawing
                */
-
+               
+               /*
+                       Calculate general brightness
+               */
                u32 daynight_ratio = client.getDayNightRatio();
-               u8 l = decode_light((daynight_ratio * LIGHT_SUN) / 1000);
+               u8 light8 = decode_light((daynight_ratio * LIGHT_SUN) / 1000);
+               brightness = (float)light8/255.0;
                video::SColor bgcolor = video::SColor(
                                255,
-                               bgcolor_bright.getRed() * l / 255,
-                               bgcolor_bright.getGreen() * l / 255,
-                               bgcolor_bright.getBlue() * l / 255);
-                               /*skycolor.getRed() * l / 255,
-                               skycolor.getGreen() * l / 255,
-                               skycolor.getBlue() * l / 255);*/
-
-               float brightness = (float)l/255.0;
+                               bgcolor_bright.getRed() * brightness,
+                               bgcolor_bright.getGreen() * brightness,
+                               bgcolor_bright.getBlue() * brightness);
+                               /*skycolor.getRed() * brightness,
+                               skycolor.getGreen() * brightness,
+                               skycolor.getBlue() * brightness);*/
 
                /*
                        Update skybox
                */
                if(fabs(brightness - old_brightness) > 0.01)
-                       update_skybox(driver, smgr, skybox, brightness);
+                       update_skybox(driver, tsrc, smgr, skybox, brightness);
 
                /*
                        Update clouds
index 7b723e958daa79425be4211d373c2bc82bad3671..d589c5ec928aad03deb166437d433a52953f820b 100644 (file)
@@ -174,8 +174,13 @@ public:
                        ContentFeatures *f = &m_content_features[i];
                        for(u16 j=0; j<6; j++)
                                tsrc->updateAP(f->tiles[j].texture);
-                       if(f->special_atlas)
+                       if(f->special_atlas){
                                tsrc->updateAP(*(f->special_atlas));
+                               if(f->special_material)
+                                       f->special_material->setTexture(0, f->special_atlas->atlas);
+                               if(f->special_material2)
+                                       f->special_material2->setTexture(0, f->special_atlas->atlas);
+                       }
                }
 #endif
        }
index 5aba69c48824dd530fd8cc1cbe5e969c73a28ace..0430621e7da629e363a994f85d10e9cdf6a13a95 100644 (file)
@@ -122,6 +122,9 @@ struct ContentFeatures
        // Special irrlicht material, used sometimes
        video::SMaterial *special_material;
        video::SMaterial *special_material2;
+       // Currently used for fetching liquid texture coordinates
+       // - This is also updated to the above two (if they are non-NULL)
+       //   when textures are updated
        AtlasPointer *special_atlas;
 #endif
 
index 8ab92d10548e6d9e1639118fd296045f20cc7a50..b0e1fbf5af3b97ffbdadf02582f51628babfe1b8 100644 (file)
@@ -145,6 +145,95 @@ std::string getTexturePath(const std::string &filename)
        return fullpath;
 }
 
+/*
+       An internal variant of AtlasPointer with more data.
+       (well, more like a wrapper)
+*/
+
+struct SourceAtlasPointer
+{
+       std::string name;
+       AtlasPointer a;
+       video::IImage *atlas_img; // The source image of the atlas
+       // Integer variants of position and size
+       v2s32 intpos;
+       v2u32 intsize;
+
+       SourceAtlasPointer(
+                       const std::string &name_,
+                       AtlasPointer a_=AtlasPointer(0, NULL),
+                       video::IImage *atlas_img_=NULL,
+                       v2s32 intpos_=v2s32(0,0),
+                       v2u32 intsize_=v2u32(0,0)
+               ):
+               name(name_),
+               a(a_),
+               atlas_img(atlas_img_),
+               intpos(intpos_),
+               intsize(intsize_)
+       {
+       }
+};
+
+/*
+       SourceImageCache: A cache used for storing source images.
+*/
+
+class SourceImageCache
+{
+public:
+       void insert(const std::string &name, video::IImage *img)
+       {
+               assert(img);
+               core::map<std::string, video::IImage*>::Node *n;
+               n = m_images.find(name);
+               if(n){
+                       video::IImage *oldimg = n->getValue();
+                       if(oldimg)
+                               oldimg->drop();
+               }
+               img->grab();
+               m_images[name] = img;
+       }
+       video::IImage* get(const std::string &name)
+       {
+               core::map<std::string, video::IImage*>::Node *n;
+               n = m_images.find(name);
+               if(n)
+                       return n->getValue();
+               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;
+               n = m_images.find(name);
+               if(n){
+                       n->getValue()->grab(); // Grab for caller
+                       return n->getValue();
+               }
+               video::IVideoDriver* driver = device->getVideoDriver();
+               std::string path = getTexturePath(name.c_str());
+               if(path == ""){
+                       infostream<<"SourceImageCache::getOrLoad(): No path found for \""
+                                       <<name<<"\""<<std::endl;
+                       return NULL;
+               }
+               infostream<<"SourceImageCache::getOrLoad(): Loading path \""<<path
+                               <<"\""<<std::endl;
+               video::IImage *img = driver->createImageFromFile(path.c_str());
+               // Even if could not be loaded, put as NULL
+               //m_images[name] = img;
+               if(img){
+                       m_images[name] = img;
+                       img->grab(); // Grab for caller
+               }
+               return img;
+       }
+private:
+       core::map<std::string, video::IImage*> m_images;
+};
+
 /*
        TextureSource
 */
@@ -209,9 +298,7 @@ public:
        */
        u32 getTextureIdDirect(const std::string &name);
 
-       /*
-               Finds out the name of a cached texture.
-       */
+       // Finds out the name of a cached texture.
        std::string getTextureName(u32 id);
 
        /*
@@ -236,29 +323,25 @@ public:
                return ap.atlas;
        }
 
-       /*
-               Update new texture pointer and texture coordinates to an
-               AtlasPointer based on it's texture id
-       */
+       // Update new texture pointer and texture coordinates to an
+       // AtlasPointer based on it's texture id
        void updateAP(AtlasPointer &ap);
 
-       /*
-               Processes queued texture requests from other threads.
-
-               Shall be called from the main thread.
-       */
+       // Processes queued texture requests from other threads.
+       // Shall be called from the main thread.
        void processQueue();
        
-       /*
-               Build the main texture atlas which contains most of the
-               textures.
-       */
-       void buildMainAtlas(class IGameDef *gamedef);
+       // Insert an image into the cache without touching the filesystem.
+       // Shall be called from the main thread.
+       void insertSourceImage(const std::string &name, video::IImage *img);
        
-       /*
-               Insert an image into the cache without touching the filesystem.
-       */
-       void insertImage(const std::string &name, video::IImage *img);
+       // Rebuild images and textures from the current set of source images
+       // Shall be called from the main thread.
+       void rebuildImagesAndTextures();
+
+       // Build the main texture atlas which contains most of the
+       // textures.
+       void buildMainAtlas(class IGameDef *gamedef);
        
 private:
        
@@ -267,6 +350,10 @@ private:
        // The irrlicht device
        IrrlichtDevice *m_device;
        
+       // Cache of source images
+       // This should be only accessed from the main thread
+       SourceImageCache m_sourcecache;
+
        // A texture id is index in this array.
        // The first position contains a NULL texture.
        core::array<SourceAtlasPointer> m_atlaspointer_cache;
@@ -376,7 +463,7 @@ void make_progressbar(float value, video::IImage *image);
        if baseimg is NULL, it is created. Otherwise stuff is made on it.
 */
 bool generate_image(std::string part_of_name, video::IImage *& baseimg,
-               IrrlichtDevice *device);
+               IrrlichtDevice *device, SourceImageCache *sourcecache);
 
 /*
        Generates an image from a full string like
@@ -385,7 +472,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
        This is used by buildMainAtlas().
 */
 video::IImage* generate_image_from_scratch(std::string name,
-               IrrlichtDevice *device);
+               IrrlichtDevice *device, SourceImageCache *sourcecache);
 
 /*
        This method generates all the textures
@@ -525,7 +612,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
        //infostream<<"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)
+       if(!generate_image(last_part_of_name, baseimg, m_device, &m_sourcecache))
        {
                infostream<<"getTextureIdDirect(): "
                                "failed to generate \""<<last_part_of_name<<"\""
@@ -627,6 +714,91 @@ void TextureSource::processQueue()
        }
 }
 
+void TextureSource::insertSourceImage(const std::string &name, video::IImage *img)
+{
+       infostream<<"TextureSource::insertSourceImage(): name="<<name<<std::endl;
+       
+       assert(get_current_thread_id() == m_main_thread);
+       
+       m_sourcecache.insert(name, img);
+
+#if 0
+       JMutexAutoLock lock(m_atlaspointer_cache_mutex);
+
+       video::IVideoDriver* driver = m_device->getVideoDriver();
+       assert(driver);
+
+       // Create texture
+       video::ITexture *t = driver->addTexture(name.c_str(), img);
+
+       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;
+       n = m_name_to_id.find(name);
+       // If it exists, we will replace the old definition
+       if(n){
+               id = n->getValue();
+               reuse_old_id = true;
+       }
+       
+       // Create AtlasPointer
+       AtlasPointer ap(id);
+       ap.atlas = t;
+       ap.pos = v2f(0,0);
+       ap.size = v2f(1,1);
+       ap.tiled = 0;
+       core::dimension2d<u32> dim = img->getDimension();
+
+       // Create SourceAtlasPointer and add to containers
+       SourceAtlasPointer nap(name, ap, img, v2s32(0,0), dim);
+       if(reuse_old_id)
+               m_atlaspointer_cache[id] = nap;
+       else
+               m_atlaspointer_cache.push_back(nap);
+       m_name_to_id[name] = id;
+#endif
+}
+       
+void TextureSource::rebuildImagesAndTextures()
+{
+       JMutexAutoLock lock(m_atlaspointer_cache_mutex);
+
+       /*// Oh well... just clear everything, they'll load sometime.
+       m_atlaspointer_cache.clear();
+       m_name_to_id.clear();*/
+
+       video::IVideoDriver* driver = m_device->getVideoDriver();
+       
+       // Remove source images from textures to disable inheriting textures
+       // from existing textures
+       /*for(u32 i=0; i<m_atlaspointer_cache.size(); i++){
+               SourceAtlasPointer *sap = &m_atlaspointer_cache[i];
+               sap->atlas_img->drop();
+               sap->atlas_img = NULL;
+       }*/
+       
+       // Recreate textures
+       for(u32 i=0; i<m_atlaspointer_cache.size(); i++){
+               SourceAtlasPointer *sap = &m_atlaspointer_cache[i];
+               video::IImage *img =
+                       generate_image_from_scratch(sap->name, m_device, &m_sourcecache);
+               // Create texture from resulting image
+               video::ITexture *t = NULL;
+               if(img)
+                       t = driver->addTexture(sap->name.c_str(), img);
+               
+               // Replace texture
+               sap->a.atlas = t;
+               sap->a.pos = v2f(0,0);
+               sap->a.size = v2f(1,1);
+               sap->a.tiled = 0;
+               sap->atlas_img = img;
+               sap->intpos = v2s32(0,0);
+               sap->intsize = img->getDimension();
+       }
+}
+
 void TextureSource::buildMainAtlas(class IGameDef *gamedef) 
 {
        assert(gamedef->tsrc() == this);
@@ -711,20 +883,9 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
        {
                std::string name = i.getNode()->getKey();
 
-               /*video::IImage *img = driver->createImageFromFile(
-                               getTexturePath(name.c_str()).c_str());
-               if(img == NULL)
-                       continue;
-               
-               core::dimension2d<u32> dim = img->getDimension();
-               // Make a copy with the right color format
-               video::IImage *img2 =
-                               driver->createImage(video::ECF_A8R8G8B8, dim);
-               img->copyTo(img2);
-               img->drop();*/
-               
                // Generate image by name
-               video::IImage *img2 = generate_image_from_scratch(name, m_device);
+               video::IImage *img2 = generate_image_from_scratch(name, m_device,
+                               &m_sourcecache);
                if(img2 == NULL)
                {
                        infostream<<"TextureSource::buildMainAtlas(): Couldn't generate texture atlas: Couldn't generate image \""<<name<<"\""<<std::endl;
@@ -810,9 +971,9 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
                if(n){
                        id = n->getValue();
                        reuse_old_id = true;
+                       infostream<<"TextureSource::buildMainAtlas(): "
+                                       <<"Replacing old AtlasPointer"<<std::endl;
                }
-               infostream<<"TextureSource::buildMainAtlas(): "
-                               <<"Replacing old AtlasPointer"<<std::endl;
 
                // Create AtlasPointer
                AtlasPointer ap(id);
@@ -867,48 +1028,8 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
        driver->writeImageToFile(atlas_img, atlaspath.c_str());*/
 }
 
-void TextureSource::insertImage(const std::string &name, video::IImage *img)
-{
-       infostream<<"TextureSource::insertImage(): name="<<name<<std::endl;
-       
-       JMutexAutoLock lock(m_atlaspointer_cache_mutex);
-
-       video::IVideoDriver* driver = m_device->getVideoDriver();
-       assert(driver);
-
-       // Create texture
-       video::ITexture *t = driver->addTexture(name.c_str(), img);
-
-       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;
-       n = m_name_to_id.find(name);
-       // If it exists, we will replace the old definition
-       if(n){
-               id = n->getValue();
-               reuse_old_id = true;
-       }
-       
-       // Create AtlasPointer
-       AtlasPointer ap(id);
-       ap.atlas = t;
-       ap.pos = v2f(0,0);
-       ap.size = v2f(1,1);
-       ap.tiled = 0;
-       core::dimension2d<u32> dim = img->getDimension();
-
-       // Create SourceAtlasPointer and add to containers
-       SourceAtlasPointer nap(name, ap, img, v2s32(0,0), dim);
-       if(reuse_old_id)
-               m_atlaspointer_cache[id] = nap;
-       else
-               m_atlaspointer_cache.push_back(nap);
-       m_name_to_id[name] = id;
-}
-       
 video::IImage* generate_image_from_scratch(std::string name,
-               IrrlichtDevice *device)
+               IrrlichtDevice *device, SourceImageCache *sourcecache)
 {
        /*infostream<<"generate_image_from_scratch(): "
                        "\""<<name<<"\""<<std::endl;*/
@@ -951,7 +1072,8 @@ video::IImage* generate_image_from_scratch(std::string name,
                /*infostream<<"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);
+               baseimg = generate_image_from_scratch(base_image_name, device,
+                               sourcecache);
        }
        
        /*
@@ -963,7 +1085,7 @@ video::IImage* generate_image_from_scratch(std::string name,
        //infostream<<"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)
+       if(!generate_image(last_part_of_name, baseimg, device, sourcecache))
        {
                infostream<<"generate_image_from_scratch(): "
                                "failed to generate \""<<last_part_of_name<<"\""
@@ -975,7 +1097,7 @@ video::IImage* generate_image_from_scratch(std::string name,
 }
 
 bool generate_image(std::string part_of_name, video::IImage *& baseimg,
-               IrrlichtDevice *device)
+               IrrlichtDevice *device, SourceImageCache *sourcecache)
 {
        video::IVideoDriver* driver = device->getVideoDriver();
        assert(driver);
@@ -983,18 +1105,12 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
        // Stuff starting with [ are special commands
        if(part_of_name[0] != '[')
        {
-               // A normal texture; load it from a file
-               std::string path = getTexturePath(part_of_name.c_str());
-               /*infostream<<"generate_image(): Loading path \""<<path
-                               <<"\""<<std::endl;*/
-               
-               video::IImage *image = driver->createImageFromFile(path.c_str());
+               video::IImage *image = sourcecache->getOrLoad(part_of_name, device);
 
                if(image == NULL)
                {
                        infostream<<"generate_image(): Could not load image \""
-                    <<part_of_name<<"\" from path \""<<path<<"\""
-                                       <<" while building texture"<<std::endl;
+                    <<part_of_name<<"\""<<" while building texture"<<std::endl;
 
                        //return false;
 
@@ -1099,8 +1215,7 @@ 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 = driver->createImageFromFile(
-                                       getTexturePath("crack.png").c_str());
+                       video::IImage *img_crack = sourcecache->getOrLoad("crack.png", device);
                
                        if(img_crack)
                        {
@@ -1186,8 +1301,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                                infostream<<"Adding \""<<filename
                                                <<"\" to combined ("<<x<<","<<y<<")"
                                                <<std::endl;
-                               video::IImage *img = driver->createImageFromFile(
-                                               getTexturePath(filename.c_str()).c_str());
+                               video::IImage *img = sourcecache->getOrLoad(filename, device);
                                if(img)
                                {
                                        core::dimension2d<u32> dim = img->getDimension();
@@ -1248,10 +1362,10 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
 
                        std::string path = getTexturePath(filename.c_str());
 
-                       infostream<<"generate_image(): Loading path \""<<path
+                       infostream<<"generate_image(): Loading file \""<<filename
                                        <<"\""<<std::endl;
                        
-                       video::IImage *image = driver->createImageFromFile(path.c_str());
+                       video::IImage *image = sourcecache->getOrLoad(filename, device);
                        
                        if(image == NULL)
                        {
@@ -1297,17 +1411,15 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        u32 b1 = stoi(sf.next(":"));
                        std::string filename = sf.next("");
 
-                       std::string path = getTexturePath(filename.c_str());
-
-                       infostream<<"generate_image(): Loading path \""<<path
+                       infostream<<"generate_image(): Loading file \""<<filename
                                        <<"\""<<std::endl;
                        
-                       video::IImage *image = driver->createImageFromFile(path.c_str());
+                       video::IImage *image = sourcecache->getOrLoad(filename, device);
                        
                        if(image == NULL)
                        {
-                               infostream<<"generate_image(): Loading path \""
-                                               <<path<<"\" failed"<<std::endl;
+                               infostream<<"generate_image(): Loading file \""
+                                               <<filename<<"\" failed"<<std::endl;
                        }
                        else
                        {
@@ -1356,17 +1468,15 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        u32 b2 = stoi(sf.next(":"));
                        std::string filename = sf.next("");
 
-                       std::string path = getTexturePath(filename.c_str());
-
-                       infostream<<"generate_image(): Loading path \""<<path
+                       infostream<<"generate_image(): Loading filename \""<<filename
                                        <<"\""<<std::endl;
                        
-                       video::IImage *image = driver->createImageFromFile(path.c_str());
+                       video::IImage *image = sourcecache->getOrLoad(filename, device);
                        
                        if(image == NULL)
                        {
-                               infostream<<"generate_image(): Loading path \""
-                                               <<path<<"\" failed"<<std::endl;
+                               infostream<<"generate_image(): Loading file \""
+                                               <<filename<<"\" failed"<<std::endl;
                        }
                        else
                        {
@@ -1419,14 +1529,14 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        std::string imagename_right = sf.next("{");
 
 #if 1
-                       //TODO
+                       // TODO: Create cube with different textures on different sides
 
                        if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
                        {
                                infostream<<"generate_image(): EVDF_RENDER_TO_TARGET"
                                                " not supported. Creating fallback image"<<std::endl;
                                baseimg = generate_image_from_scratch(
-                                               imagename_top, device);
+                                               imagename_top, device, sourcecache);
                                return true;
                        }
                        
@@ -1437,14 +1547,15 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        
                        // Generate images for the faces of the cube
                        video::IImage *img_top = generate_image_from_scratch(
-                                       imagename_top, device);
+                                       imagename_top, device, sourcecache);
                        video::IImage *img_left = generate_image_from_scratch(
-                                       imagename_left, device);
+                                       imagename_left, device, sourcecache);
                        video::IImage *img_right = generate_image_from_scratch(
-                                       imagename_right, device);
+                                       imagename_right, device, sourcecache);
                        assert(img_top && img_left && img_right);
 
-                       // TODO: Create textures from images
+                       // Create textures from images
+                       // TODO: Use them all
                        video::ITexture *texture_top = driver->addTexture(
                                        (imagename_top + "__temp__").c_str(), img_top);
                        assert(texture_top);
@@ -1515,7 +1626,8 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
                        // Unset render target
                        driver->setRenderTarget(0, true, true, 0);
 
-                       //TODO: Free textures of images
+                       // Free textures of images
+                       // TODO: When all are used, free them all
                        driver->removeTexture(texture_top);
                        
                        // Create image of render target
index 17ba74e3396d6633feea8e1ed063d278cbda3e96..23849ca1fcc382258797be30e1e321947efea598 100644 (file)
@@ -93,34 +93,6 @@ struct AtlasPointer
        float y1(){ return pos.Y + size.Y; }
 };
 
-/*
-       An internal variant of the former with more data.
-*/
-struct SourceAtlasPointer
-{
-       std::string name;
-       AtlasPointer a;
-       video::IImage *atlas_img; // The source image of the atlas
-       // Integer variants of position and size
-       v2s32 intpos;
-       v2u32 intsize;
-
-       SourceAtlasPointer(
-                       const std::string &name_,
-                       AtlasPointer a_=AtlasPointer(0, NULL),
-                       video::IImage *atlas_img_=NULL,
-                       v2s32 intpos_=v2s32(0,0),
-                       v2u32 intsize_=v2u32(0,0)
-               ):
-               name(name_),
-               a(a_),
-               atlas_img(atlas_img_),
-               intpos(intpos_),
-               intsize(intsize_)
-       {
-       }
-};
-
 /*
        TextureSource creates and caches textures.
 */
@@ -157,9 +129,9 @@ public:
        virtual void updateAP(AtlasPointer &ap){};
 
        virtual void processQueue()=0;
+       virtual void insertSourceImage(const std::string &name, video::IImage *img)=0;
+       virtual void rebuildImagesAndTextures()=0;
        virtual void buildMainAtlas(class IGameDef *gamedef)=0;
-       // img is eaten, do not drop it
-       virtual void insertImage(const std::string &name, video::IImage *img)=0;
 };
 
 IWritableTextureSource* createTextureSource(IrrlichtDevice *device);