X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftile.cpp;h=7cad1b83692399392cacbf6ede423d0c543fc014;hb=d5029958b9017ad89775bc4f68c4de3db603e618;hp=25f8a000bd72b1886a218e329948a510e5b55ce3;hpb=0983f65da7f8302fe6db7bc922a95187584b4e63;p=oweals%2Fminetest.git diff --git a/src/tile.cpp b/src/tile.cpp index 25f8a000b..7cad1b836 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -3,16 +3,16 @@ Minetest-c55 Copyright (C) 2010-2011 celeron55, Perttu Ahola 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 -the Free Software Foundation; either version 2 of the License, or +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -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 @@ -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 @@ -131,6 +133,18 @@ std::string getTexturePath(const std::string &filename) fullpath = getImagePath(testpath); } + /* + Check from $user/textures/all + */ + if(fullpath == "") + { + std::string texture_path = porting::path_user + DIR_DELIM + + "textures" + DIR_DELIM + "all"; + std::string testpath = texture_path + DIR_DELIM + filename; + // Check all filename extensions. Returns "" if not found. + fullpath = getImagePath(testpath); + } + /* Check from default data directory */ @@ -358,6 +372,18 @@ public: // 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. @@ -386,6 +412,9 @@ private: // This should be only accessed from the main thread SourceImageCache m_sourcecache; + // Thread-safe cache of what source images are known (true = known) + MutexedMap m_source_image_existence; + // A texture id is index in this array. // The first position contains a NULL texture. core::array m_atlaspointer_cache; @@ -490,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 @@ -762,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() @@ -818,7 +853,10 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) JMutexAutoLock lock(m_atlaspointer_cache_mutex); // Create an image of the right size - core::dimension2d atlas_dim(1024,1024); + core::dimension2d max_dim = driver->getMaxTextureSize(); + core::dimension2d atlas_dim(2048,2048); + atlas_dim.Width = MYMIN(atlas_dim.Width, max_dim.Width); + atlas_dim.Height = MYMIN(atlas_dim.Height, max_dim.Height); video::IImage *atlas_img = driver->createImage(video::ECF_A8R8G8B8, atlas_dim); //assert(atlas_img); @@ -843,7 +881,7 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) const ContentFeatures &f = ndef->get(j); for(u32 i=0; i<6; i++) { - std::string name = f.tname_tiles[i]; + std::string name = f.tiledef[i].name; sourcelist[name] = true; } } @@ -859,16 +897,17 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) infostream< pos_in_atlas(0,0); + pos_in_atlas.X = column_padding; pos_in_atlas.Y = padding; for(core::map::Iterator @@ -889,8 +928,8 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) core::dimension2d dim = img2->getDimension(); - // Don't add to atlas if image is large - core::dimension2d max_size_in_atlas(32,32); + // Don't add to atlas if image is too large + core::dimension2d max_size_in_atlas(64,64); if(dim.Width > max_size_in_atlas.Width || dim.Height > max_size_in_atlas.Height) { @@ -902,14 +941,14 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef) // Wrap columns and stop making atlas if atlas is full if(pos_in_atlas.Y + dim.Height > atlas_dim.Height) { - if(pos_in_atlas.X > (s32)atlas_dim.Width - 256 - padding){ + if(pos_in_atlas.X > (s32)atlas_dim.Width - column_width - column_padding){ errorstream<<"TextureSource::buildMainAtlas(): " <<"Atlas is full, not adding more textures." <setPixel(x,dst_y,c); } + for(u32 side=0; side<2; side++) // left and right + for(s32 x0=0; x0getPixel(src_x, src_y); + atlas_img->setPixel(dst_x,dst_y,c); + } + img2->drop(); /* @@ -1154,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 pos_from(0,0); // Blit - image->copyToWithAlpha(baseimg, pos_to, + /*image->copyToWithAlpha(baseimg, pos_to, core::rect(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(); } @@ -1227,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) { @@ -1266,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(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); } } @@ -1295,7 +1361,11 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, u32 h0 = stoi(sf.next(":")); infostream<<"combined w="<createImage(video::ECF_A8R8G8B8, dim); img->copyTo(img2); img->drop(); - img2->copyToWithAlpha(baseimg, pos_base, + /*img2->copyToWithAlpha(baseimg, pos_base, core::rect(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 @@ -1564,6 +1635,86 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, image->drop(); } } + /* + [lowpart:percent:filename + Adds the lower part of a texture + */ + else if(part_of_name.substr(0,9) == "[lowpart:") + { + Strfnd sf(part_of_name); + sf.next(":"); + u32 percent = stoi(sf.next(":")); + std::string filename = sf.next(":"); + //infostream<<"power part "<createImage(video::ECF_A8R8G8B8, v2u32(16,16)); + video::IImage *img = sourcecache->getOrLoad(filename, device); + if(img) + { + core::dimension2d dim = img->getDimension(); + core::position2d pos_base(0, 0); + video::IImage *img2 = + driver->createImage(video::ECF_A8R8G8B8, dim); + img->copyTo(img2); + img->drop(); + core::position2d clippos(0, 0); + clippos.Y = dim.Height * (100-percent) / 100; + core::dimension2d clipdim = dim; + clipdim.Height = clipdim.Height * percent / 100 + 1; + core::rect cliprect(clippos, clipdim); + img2->copyToWithAlpha(baseimg, pos_base, + core::rect(v2s32(0,0), dim), + video::SColor(255,255,255,255), + &cliprect); + img2->drop(); + } + } + /* + [verticalframe:N:I + Crops a frame of a vertical animation. + N = frame count, I = frame index + */ + else if(part_of_name.substr(0,15) == "[verticalframe:") + { + Strfnd sf(part_of_name); + sf.next(":"); + u32 frame_count = stoi(sf.next(":")); + u32 frame_index = stoi(sf.next(":")); + + if(baseimg == NULL){ + errorstream<<"generate_image(): baseimg!=NULL " + <<"for part_of_name=\""<getDimension(); + frame_size.Y /= frame_count; + + video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, + frame_size); + if(!img){ + errorstream<<"generate_image(): Could not create image " + <<"for part_of_name=\""<fill(video::SColor(0,0,0,0)); + + core::dimension2d dim = frame_size; + core::position2d pos_dst(0, 0); + core::position2d pos_src(0, frame_index * frame_size.Y); + baseimg->copyToWithAlpha(img, pos_dst, + core::rect(pos_src, dim), + video::SColor(255,255,255,255), + NULL); + // Replace baseimg + baseimg->drop(); + baseimg = img; + } else { errorstream<<"generate_image(): Invalid " @@ -1605,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; y0getPixel(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)