diff options
Diffstat (limited to 'src/wall-atlas.cpp')
-rw-r--r-- | src/wall-atlas.cpp | 157 |
1 files changed, 88 insertions, 69 deletions
diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp index d73510bb..24910549 100644 --- a/src/wall-atlas.cpp +++ b/src/wall-atlas.cpp @@ -1,6 +1,5 @@ #include "wall-atlas.hpp" #include "compat/assert.hpp" -#include "compat/function2.hpp" #include <utility> #include <Magnum/ImageView.h> #include <Magnum/GL/TextureFormat.h> @@ -9,103 +8,123 @@ namespace floormat { namespace { -#define FM_FRAMESET_ITER(Name) do { if (fun( #Name ## _s, const_cast<Self>(frameset.Name), wall_frame_set::type::Name)) return; } while(false) -#define FM_FRAMESET_ITER2(Str, Name) do { if (fun( Str, const_cast<Self>(frameset.Name), wall_frame_set::type::Name )) return; } while(false) - -template<typename Self> -CORRADE_ALWAYS_INLINE void visit_frameset_impl(const wall_frame_set& frameset, auto&& fun) +inline uint8_t direction_count_(std::array<uint8_t, 4> rot_to_direction) { - FM_FRAMESET_ITER(wall); - FM_FRAMESET_ITER(overlay); - FM_FRAMESET_ITER(side); - FM_FRAMESET_ITER(top); - FM_FRAMESET_ITER2("corner-L"_s, corner_L); - FM_FRAMESET_ITER2("corner-R"_s, corner_R); + uint8_t total = 0; + for (uint8_t x : rot_to_direction) + if (x != (uint8_t)-1) + total++; + return total; } -#undef FM_FRAMESET_ITER - } // namespace -size_t wall_atlas::enum_to_index(enum rotation r) -{ - static_assert(rotation_COUNT == rotation{8}); - fm_debug_assert(r < rotation_COUNT); +namespace Wall { - auto x = uint8_t(r); - x >>= 1; - return x; -} +} // namespace Wall -bool wall_frames::is_empty() const noexcept -{ - return count == 0; -} - -bool wall_frame_set::is_empty() const noexcept -{ - return !wall.is_empty() && !overlay.is_empty() && !side.is_empty() && !top.is_empty() && - !corner_L.is_empty() && !corner_R.is_empty(); -} +wall_atlas::wall_atlas() noexcept = default; +wall_atlas::~wall_atlas() noexcept = default; -wall_atlas::wall_atlas(wall_info info, const ImageView2D& image, - Array<wall_frame> frames, - std::unique_ptr<wall_frame_set[]> framesets, - uint8_t frameset_count, - std::array<uint8_t, 4> frameset_indexes) : - _framesets{std::move(framesets)}, _frame_array{std::move(frames)}, _info(std::move(info)), - _frameset_indexes{frameset_indexes}, - _frameset_count{(uint8_t)frameset_count} +wall_atlas::wall_atlas(Info info, const ImageView2D& image, + Array<Frame> frames, + Array<Direction> directions, + std::array<DirArrayIndex, 4> direction_to_DirArrayIndex) + : _dir_array{ std::move(directions) }, _frame_array{ std::move(frames) }, + _info{ std::move(info) }, + _direction_to_Direction_array_index{ direction_to_DirArrayIndex } { - { fm_assert(frameset_count <= 4); - uint8_t counts[4] = {}, total = 0; - - for (auto i = 0uz; i < frameset_count; i++) - if (frameset_indexes[i] != (uint8_t)-1) - { - fm_assert(++counts[i] == 1); - total++; - } - fm_assert(total == frameset_count); - } - _texture.setLabel(_info.name) .setWrapping(GL::SamplerWrapping::ClampToEdge) .setMagnificationFilter(GL::SamplerFilter::Nearest) .setMinificationFilter(GL::SamplerFilter::Linear) - .setMaxAnisotropy(1) + .setMaxAnisotropy(1) // todo? .setBorderColor(Color4{1, 0, 0, 1}) .setStorage(1, GL::textureFormat(image.format()), image.size()) .setSubImage(0, {}, image); } -wall_atlas::wall_atlas() = default; -wall_atlas::~wall_atlas() noexcept = default; -ArrayView<const wall_frame> wall_atlas::frame_array() const { return _frame_array; } -StringView wall_atlas::name() const { return _info.name; } -const wall_frame_set& wall_atlas::frameset(enum rotation r) const { return frameset(enum_to_index(r)); } +auto wall_atlas::get_Direction(Direction_ num) const -> Direction* +{ + fm_debug_assert(num < Direction_::COUNT); + + if (_dir_array.isEmpty()) [[unlikely]] + return {}; + if (auto idx = _direction_to_Direction_array_index[(uint8_t)num]) + return const_cast<Direction*>(&_dir_array[idx.val]); + return {}; +} + +auto wall_atlas::frames(const Group& group) const -> ArrayView<const Frame> +{ + if (_frame_array.isEmpty()) [[unlikely]] + return {}; + const auto size = _frame_array.size(); (void)size; + const auto index = group.index, count = group.count; + fm_assert(index < size && index <= index + count && index + count <= size); + return { &_frame_array[index], count }; +} -void wall_frame_set::visit(const fu2::function_view<bool(StringView name, const wall_frames& frames, type tag) const>& fun) const& +auto wall_atlas::group(size_t dir, Tag tag) const -> const Group* { - visit_frameset_impl<const wall_frames&>(*this, fun); + fm_assert(tag < Tag::COUNT); + const auto* const set_ = direction(dir); + if (!set_) + return {}; + const auto& set = *set_; + + const auto memfn = set.members[(size_t)tag].member; + const Group& ret = set.*memfn; + if (ret.is_empty()) + return {}; + return &ret; } -void wall_frame_set::visit(const fu2::function_view<bool(StringView name, wall_frames& frames, type tag) const>& fun) & +auto wall_atlas::group(const Direction& dir, Tag tag) const -> const Group* { - visit_frameset_impl<wall_frames&>(*this, fun); + fm_assert(tag < Tag::COUNT); + const auto memfn = dir.members[(size_t)tag].member; + const Group& ret = dir.*memfn; + if (ret.is_empty()) + return {}; + return &ret; } -const wall_frame_set& wall_atlas::frameset(size_t i) const +auto wall_atlas::group(const Direction* dir, Tag tag) const -> const Group* { - fm_assert(i < 4 && _frameset_indexes[i] != (uint8_t)-1); - return _framesets[i]; + fm_debug_assert(dir != nullptr); + return group(*dir, tag); } -ArrayView<const wall_frame> wall_frames::items(const wall_atlas& a) const +auto wall_atlas::direction(size_t dir) const -> const Direction* { - auto sz = a.frame_array().size(); (void)sz; - fm_assert(index < sz && index + count <= sz); - return { a.frame_array() + index, count }; + return get_Direction(Direction_(dir)); +} + +uint8_t wall_atlas::direction_count() const { return (uint8_t)_dir_array.size(); } +auto wall_atlas::raw_frame_array() const -> ArrayView<const Frame> { return _frame_array; } +StringView wall_atlas::name() const { return _info.name; } + +size_t wall_atlas::enum_to_index(enum rotation r) +{ + static_assert(rotation_COUNT == rotation{8}); + fm_debug_assert(r < rotation_COUNT); + + auto x = uint8_t(r); + x >>= 1; + return x; } } // namespace floormat + +namespace floormat::Wall { + +bool Direction::is_empty() const noexcept +{ + for (auto [str, member, tag] : Direction::members) + if (const auto& val = this->*member; !val.is_empty()) + return false; + return true; +} + +} // namespace floormat::Wall |