diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-11-05 21:23:07 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-11-05 21:23:07 +0100 |
commit | 7f82a729ae5074beafb6b4fd50d2f025dd05dfbe (patch) | |
tree | 28f2d5b968d75ff9e6f4eb6f03174d46359a0dc0 /src | |
parent | 0c9e57bfdc2ac5bead6c5f4984d3ae26eaeb5769 (diff) |
wip broken
Diffstat (limited to 'src')
-rw-r--r-- | src/wall-atlas.cpp | 157 | ||||
-rw-r--r-- | src/wall-atlas.hpp | 114 |
2 files changed, 156 insertions, 115 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 diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp index 544bc5b7..6a94b34f 100644 --- a/src/wall-atlas.hpp +++ b/src/wall-atlas.hpp @@ -1,93 +1,115 @@ #pragma once #include "compat/defs.hpp" -#include "compat/function2.fwd.hpp" #include "src/rotation.hpp" #include <array> -#include <memory> #include <Corrade/Containers/Array.h> #include <Corrade/Containers/String.h> #include <Magnum/Math/Vector2.h> #include <Magnum/Math/Color.h> #include <Magnum/GL/Texture.h> -namespace floormat { +namespace floormat { class wall_atlas; } -struct wall_atlas; +namespace floormat::Wall { -struct wall_frame +struct Frame { Vector2ui offset = { (unsigned)-1, (unsigned)-1 }; }; -struct wall_frames +struct Group { - bool is_empty() const noexcept; - ArrayView<const wall_frame> items(const wall_atlas& a) const; - uint32_t index = (uint32_t)-1, count = 0; - Vector2ui pixel_size; Color4 tint_mult{1,1,1,1}; Color3 tint_add; uint8_t from_rotation = (uint8_t)-1; bool mirrored : 1 = false, use_default_tint : 1 = true; + + explicit operator bool() const noexcept { return !is_empty(); } + bool is_empty() const noexcept { return count == 0; } }; -struct wall_frame_set +enum class Tag : uint8_t { wall, overlay, side, top, corner_L, corner_R, COUNT }; + +enum class Direction_ : uint8_t { N, E, S, W, COUNT }; + +struct Direction { - enum class type : uint8_t { wall = 1, overlay, side, top, corner_L, corner_R, }; + using memfn_ptr = Group Direction::*; + struct member_tuple { StringView str; memfn_ptr member; Tag tag; }; + explicit operator bool() const noexcept { return !is_empty(); } bool is_empty() const noexcept; - void visit(const fu2::function_view<bool(StringView, const wall_frames&, type) const>& fun) const&; - void visit(const fu2::function_view<bool(StringView, wall_frames&, type) const>& fun) &; - - wall_frames wall, overlay, side, top; - wall_frames corner_L, corner_R; + Group wall, overlay, side, top; + Group corner_L, corner_R; + + static constexpr inline member_tuple members[] = { + { "wall"_s, &Direction::wall, Tag::wall }, + { "overlay"_s, &Direction::overlay, Tag::overlay }, + { "side"_s, &Direction::side, Tag::side }, + { "top"_s, &Direction::top, Tag::top }, + { "corner-L"_s, &Direction::corner_L, Tag::corner_L, }, + { "corner-R"_s, &Direction::corner_R, Tag::corner_R, }, + }; + static_assert(arraySize(members) == (size_t)Tag::COUNT); }; -struct wall_info +struct Info { String name = "(unnamed)"_s; unsigned depth = 0; }; -struct wall_atlas_def -{ - wall_info info; - std::unique_ptr<wall_frame_set[]> framesets; - std::array<uint8_t, 4> frameset_indexes = {255, 255, 255, 255}; - uint8_t frameset_count = 0; - - Array<wall_frame> array; - uint32_t frame_count = 0; +struct DirArrayIndex { + std::uint8_t val = (uint8_t)-1; + operator bool() const { return val == (uint8_t)-1; } }; -struct wall_atlas final +} // namespace floormat::Wall + +namespace floormat { + +class wall_atlas final { - fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(wall_atlas); - wall_atlas(); + using Frame = Wall::Frame; + using Group = Wall::Group; + using Direction_ = Wall::Direction_; + using Direction = Wall::Direction; + using Info = Wall::Info; + using Tag = Wall::Tag; + using DirArrayIndex = Wall::DirArrayIndex; + + Array<Direction> _dir_array; + Array<Frame> _frame_array; + Info _info; + GL::Texture2D _texture; + std::array<DirArrayIndex, 4> _direction_to_Direction_array_index; + + Direction* get_Direction(Direction_ num) const; + +public: + fm_DECLARE_DELETED_MOVE_ASSIGNMENT(wall_atlas); + wall_atlas() noexcept; ~wall_atlas() noexcept; - 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); - static size_t enum_to_index(enum rotation x); - const wall_frame_set& frameset(size_t i) const; - const wall_frame_set& frameset(enum rotation r) const; - ArrayView<const wall_frame> frame_array() const; + wall_atlas(Info info, const ImageView2D& image, + Array<Frame> frames, Array<Direction> directions, + std::array<DirArrayIndex, 4> direction_to_DirArrayIndex); StringView name() const; + uint8_t direction_count() const; -private: - std::unique_ptr<wall_frame_set[]> _framesets; - Array<wall_frame> _frame_array; - wall_info _info; - GL::Texture2D _texture; - std::array<uint8_t, 4> _frameset_indexes; - uint8_t _frameset_count = 0; + const Group* group(size_t dir, Tag tag) const; + const Group* group(const Direction& dir, Tag tag) const; + const Group* group(const Direction* dir, Tag tag) const; + const Direction* direction(size_t dir) const; + ArrayView<const Frame> frames(const Group& a) const; + ArrayView<const Frame> raw_frame_array() const; + + static size_t enum_to_index(enum rotation x); }; + } // namespace floormat |