diff --git a/libs/util/include/psemek/util/atlas.hpp b/libs/util/include/psemek/util/atlas.hpp index 3cd894eb..75e33724 100644 --- a/libs/util/include/psemek/util/atlas.hpp +++ b/libs/util/include/psemek/util/atlas.hpp @@ -20,8 +20,16 @@ namespace psemek::util std::array end; }; - atlas(T default_value = T{}, Compare compare = Compare{}) + enum class padding_mode + { + default_value, + clamp, + }; + + atlas(T default_value = T{}, std::size_t padding = 0, padding_mode mode = padding_mode::default_value, Compare compare = Compare{}) : default_value_(std::move(default_value)) + , padding_(padding) + , padding_mode_(mode) , data_(std::move(compare)) {} @@ -36,25 +44,48 @@ namespace psemek::util if (it != data_.end()) return {it->second, false}; + std::size_t part_width = data.width() + padding_ * 2; + std::size_t part_height = data.height() + padding_ * 2; + atlas_part part; part.begin[0] = array_.width(); - part.end[0] = part.begin[0] + data.width(); + part.end[0] = part.begin[0] + part_width; part.begin[1] = 0; - part.end[1] = data.height(); + part.end[1] = part_height; - std::size_t new_width = array_.width() + data.width(); - std::size_t new_height = std::max(array_.height(), data.height()); + std::size_t new_width = array_.width() + part_width; + std::size_t new_height = std::max(array_.height(), part_height); array_.resize({new_width, new_height}, default_value_); - for (std::size_t y = 0; y < data.height(); ++y) + for (std::size_t y = 0; y < part_height; ++y) { - for (std::size_t x = 0; x < data.width(); ++x) + for (std::size_t x = 0; x < part_width; ++x) { - array_(part.begin[0] + x, part.begin[1] + y) = data(x, y); + T value; + if (padding_mode_ == padding_mode::default_value) + { + if (x < padding_ || y < padding_ || x + padding_ >= part_width || y + padding_ >= part_height) + value = default_value_; + else + value = data(x - padding_, y - padding_); + } + else + { + std::size_t xx = std::min(std::max(x, padding_), part_width - padding_ - 1); + std::size_t yy = std::min(std::max(y, padding_), part_height - padding_ - 1); + value = data(xx - padding_, yy - padding_); + } + + array_(part.begin[0] + x, part.begin[1] + y) = value; } } + part.begin[0] += padding_; + part.begin[1] += padding_; + part.end[0] -= padding_; + part.end[1] -= padding_; + data_[key] = part; return {part, true}; } @@ -74,6 +105,8 @@ namespace psemek::util private: T default_value_; + std::size_t const padding_; + padding_mode const padding_mode_; std::map data_; util::array array_; };