diff --git a/src/animated.hpp b/src/animated.hpp index f0a120df995..85298244a45 100644 --- a/src/animated.hpp +++ b/src/animated.hpp @@ -89,8 +89,9 @@ public: int get_current_frame_duration() const; int get_current_frame_time() const; const T& get_first_frame() const; + const T& get_frame(size_t n) const; const T& get_last_frame() const; - int get_frames_count() const; + size_t get_frames_count() const; void force_change() {does_not_change_ = false ; } bool does_not_change() const {return does_not_change_;} diff --git a/src/animated.i b/src/animated.i index f8c19c6133c..1d5dec4e171 100644 --- a/src/animated.i +++ b/src/animated.i @@ -283,6 +283,14 @@ const T& animated::get_first_frame() const return frames_[0].value_; } +template +const T& animated::get_frame(size_t n) const +{ + if(n >= frames_.size()) + return void_value_; + return frames_[n].value_; +} + template const T& animated::get_last_frame() const { @@ -292,7 +300,7 @@ const T& animated::get_last_frame() const } template -int animated::get_frames_count() const +size_t animated::get_frames_count() const { return frames_.size(); } diff --git a/src/builder.cpp b/src/builder.cpp index 297144fad3c..448efe49a6d 100644 --- a/src/builder.cpp +++ b/src/builder.cpp @@ -77,7 +77,21 @@ void terrain_builder::tile::rebuild_cache(const std::string& tod, logs* log) //need to break parity pattern in RNG /** @todo improve this */ unsigned int rnd = ri.rand / 7919; //just the 1000th prime - img_list.push_back(variant.images[rnd % variant.images.size()]); + const animated& anim = variant.images[rnd % variant.images.size()]; + + bool is_empty = true; + for(size_t i = 0; i < anim.get_frames_count(); ++i) { + if(!image::is_empty_hex(anim.get_frame(i))) { + is_empty = false; + break; + } + } + + if(is_empty) + continue; + + img_list.push_back(anim); + if(variant.random_start) img_list.back().set_animation_time(ri.rand % img_list.back().get_animation_duration()); diff --git a/src/image.cpp b/src/image.cpp index 9cd9d6cd729..8572ad74ee4 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -125,6 +125,9 @@ image::image_cache images_, // cache storing if each image fit in a hex image::bool_cache in_hex_info_; +// cache storing if this is an empty hex +image::bool_cache is_empty_hex_; + // caches storing the diffrent lighted cases for each image image::lit_cache lit_images_, lit_scaled_images_; @@ -174,6 +177,7 @@ void flush_cache() lit_images_.flush(); lit_scaled_images_.flush(); in_hex_info_.flush(); + is_empty_hex_.flush(); mini_terrain_cache.clear(); mini_fogged_terrain_cache.clear(); reversed_images_.clear(); @@ -572,8 +576,11 @@ surface locator::load_image_sub_file() const srcrect.y += surf->h/2 - val_.center_y_; } + // cut and hex mask, but also check and cache if empty result surface cut(cut_surface(surf, srcrect)); - surf = mask_surface(cut, get_hexmask()); + bool is_empty = false; + surf = mask_surface(cut, get_hexmask(), &is_empty); + add_to_cache(is_empty_hex_, is_empty); } return surf; @@ -689,8 +696,11 @@ void set_zoom(int amount) static surface get_hexed(const locator& i_locator) { surface image(get_image(i_locator, UNSCALED)); - // Re-cut scaled tiles according to a mask. - return mask_surface(image, get_hexmask()); + // hex cut tiles, also check and cache if empty result + bool is_empty = false; + surface res = mask_surface(image, get_hexmask(), &is_empty); + i_locator.add_to_cache(is_empty_hex_, is_empty); + return res; } static surface get_scaled_to_hex(const locator& i_locator) @@ -929,6 +939,24 @@ bool is_in_hex(const locator& i_locator) return result; } +bool is_empty_hex(const locator& i_locator) +{ + if(!i_locator.in_cache(is_empty_hex_)) { + const surface surf = get_image(i_locator, HEXED); + // emptiness of terrain image is checked during hex cut + // so, maybe in cache now, let's recheck + if(!i_locator.in_cache(is_empty_hex_)) { + //should never reach here + //but do it manually if it happens + //assert(false); + bool is_empty = false; + mask_surface(surf, get_hexmask(), &is_empty); + i_locator.add_to_cache(is_empty_hex_, is_empty); + } + } + return i_locator.locate_in_cache(is_empty_hex_); +} + surface reverse_image(const surface& surf) { diff --git a/src/image.hpp b/src/image.hpp index 14e4090e607..07f11727f9f 100644 --- a/src/image.hpp +++ b/src/image.hpp @@ -220,6 +220,10 @@ namespace image { ///return false if the image has not the standard size. bool is_in_hex(const locator& i_locator); + ///function to check if an image is empty after hex cut + ///should be only used on terrain image (cache the hex cut version) + bool is_empty_hex(const locator& i_locator); + ///function to reverse an image. The image MUST have originally been returned from ///an image:: function. Returned images have the same semantics as for get_image() ///and must be freed using SDL_FreeSurface() diff --git a/src/sdl_utils.cpp b/src/sdl_utils.cpp index f3e2107a93e..961d8d90e55 100644 --- a/src/sdl_utils.cpp +++ b/src/sdl_utils.cpp @@ -809,7 +809,7 @@ surface adjust_surface_alpha_add(const surface &surf, int amount, bool optimize) return optimize ? create_optimized_surface(nsurf) : nsurf; } -surface mask_surface(const surface &surf, const surface &mask) +surface mask_surface(const surface &surf, const surface &mask, bool* empty_result) { if(surf == NULL) { return NULL; @@ -835,6 +835,7 @@ surface mask_surface(const surface &surf, const surface &mask) return nsurf; } + bool empty = true; { surface_lock lock(nsurf); const_surface_lock mlock(nmask); @@ -854,7 +855,11 @@ surface mask_surface(const surface &surf, const surface &mask) b = (*beg); Uint8 malpha = (*mbeg) >> 24; - if (alpha > malpha) alpha = malpha; + if (alpha > malpha) { + alpha = malpha; + } + if(alpha) + empty = false; *beg = (alpha << 24) + (r << 16) + (g << 8) + b; } @@ -863,6 +868,8 @@ surface mask_surface(const surface &surf, const surface &mask) ++mbeg; } } + if(empty_result) + *empty_result = empty; return nsurf; //return create_optimized_surface(nsurf); diff --git a/src/sdl_utils.hpp b/src/sdl_utils.hpp index 16052531abc..4a7c6eb9ed6 100644 --- a/src/sdl_utils.hpp +++ b/src/sdl_utils.hpp @@ -228,7 +228,7 @@ surface adjust_surface_alpha(const surface &surf, fixed_t amount, bool optimize= surface adjust_surface_alpha_add(const surface &surf, int amount, bool optimize=true); /** Applies a mask on a surface. */ -surface mask_surface(const surface &surf, const surface &mask); +surface mask_surface(const surface &surf, const surface &mask, bool* empty_result = NULL); /** Check if a surface fit into a mask */ bool in_mask_surface(const surface &surf, const surface &mask);