summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-11-05 21:23:07 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-11-05 21:23:07 +0100
commit7f82a729ae5074beafb6b4fd50d2f025dd05dfbe (patch)
tree28f2d5b968d75ff9e6f4eb6f03174d46359a0dc0 /src
parent0c9e57bfdc2ac5bead6c5f4984d3ae26eaeb5769 (diff)
wip broken
Diffstat (limited to 'src')
-rw-r--r--src/wall-atlas.cpp157
-rw-r--r--src/wall-atlas.hpp114
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