#pragma once #include "compat/defs.hpp" #include "src/rotation.hpp" #include #include #include #include #include #include namespace floormat { class wall_atlas; } namespace floormat::Wall { struct Frame { Vector2ui offset = { (unsigned)-1, (unsigned)-1 }; bool operator==(const Frame&) const noexcept; }; struct Group { 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; // applies only to images bool mirrored : 1 = false, default_tint : 1 = true; explicit operator bool() const noexcept { return !is_empty(); } bool is_empty() const noexcept { return count == 0; } bool operator==(const Group&) const noexcept; }; 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 { 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; 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); bool operator==(const Direction&) const noexcept; }; struct Info { String name = "(unnamed)"_s, description = {}; unsigned depth = 0; bool operator==(const Info&) const noexcept; }; struct DirArrayIndex { std::uint8_t val = (uint8_t)-1; operator bool() const { return val == (uint8_t)-1; } bool operator==(const DirArrayIndex&) const noexcept; }; } // namespace floormat::Wall namespace floormat { class wall_atlas final { 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 _dir_array; Array _frame_array; Info _info; GL::Texture2D _texture; std::array _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(Info info, const ImageView2D& image, Array frames, Array directions, std::array direction_to_DirArrayIndex); StringView name() const; uint8_t direction_count() const; 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 frames(const Group& a) const; ArrayView raw_frame_array() const; static size_t enum_to_index(enum rotation x); }; } // namespace floormat