diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-12-23 11:57:25 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-12-23 11:57:25 +0100 |
commit | a737d0cea5ca8bdcd3f9cfc38e29f8a15992ca3e (patch) | |
tree | a9eff1385f0b891dc7298477768444a1ce1113fc | |
parent | 14cf3a6c5acb51a953ca193289e3eb112542e9ac (diff) |
a
-rw-r--r-- | loader/loader.hpp | 2 | ||||
-rw-r--r-- | loader/wall-atlas.cpp | 2 | ||||
-rw-r--r-- | serialize/wall-atlas.cpp | 23 | ||||
-rw-r--r-- | serialize/wall-atlas.hpp | 3 | ||||
-rw-r--r-- | src/wall-atlas.cpp | 55 | ||||
-rw-r--r-- | src/wall-atlas.hpp | 8 | ||||
-rw-r--r-- | test/json/wall-atlas-02_groups.json | 9 | ||||
-rw-r--r-- | test/wall-atlas.cpp | 27 |
8 files changed, 102 insertions, 27 deletions
diff --git a/loader/loader.hpp b/loader/loader.hpp index 02c5dc67..08881ee7 100644 --- a/loader/loader.hpp +++ b/loader/loader.hpp @@ -33,7 +33,7 @@ struct loader_ virtual std::shared_ptr<class tile_atlas> tile_atlas(StringView filename) noexcept(false) = 0; virtual ArrayView<const String> anim_atlas_list() = 0; virtual std::shared_ptr<class anim_atlas> anim_atlas(StringView name, StringView dir = ANIM_PATH) noexcept(false) = 0; - virtual std::shared_ptr<class wall_atlas> wall_atlas(StringView name, bool fail_ok = true) = 0; + virtual std::shared_ptr<class wall_atlas> wall_atlas(StringView name, bool fail_ok = true) noexcept(false) = 0; virtual ArrayView<const wall_info> wall_atlas_list() = 0; static void destroy(); static loader_& default_loader() noexcept; diff --git a/loader/wall-atlas.cpp b/loader/wall-atlas.cpp index 502cfd0c..5b7766a5 100644 --- a/loader/wall-atlas.cpp +++ b/loader/wall-atlas.cpp @@ -73,7 +73,7 @@ const wall_info& loader_impl::make_invalid_wall_atlas() return *invalid_wall_atlas; } -std::shared_ptr<class wall_atlas> loader_impl::wall_atlas(StringView name, bool fail_ok) +std::shared_ptr<class wall_atlas> loader_impl::wall_atlas(StringView name, bool fail_ok) noexcept(false) { fm_soft_assert(check_atlas_name(name)); char buf[FILENAME_MAX]; diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp index 70826e27..ca37a13a 100644 --- a/serialize/wall-atlas.cpp +++ b/serialize/wall-atlas.cpp @@ -138,23 +138,6 @@ void wall_atlas::serialize(StringView filename) const namespace floormat::Wall::detail { -uint8_t direction_index_from_name(StringView s) -{ - for (uint8_t i = 0; auto [n, _] : wall_atlas::directions) - if (n == s) - return i; - else - i++; - - fm_throw("bad rotation name '{}'"_cf, s); -} - -StringView direction_index_to_name(size_t i) -{ - fm_soft_assert(i < arraySize(wall_atlas::directions)); - return wall_atlas::directions[i].name; -} - std::vector<Frame> read_all_frames(const json& jroot) { if (!jroot.contains("frames")) @@ -224,6 +207,8 @@ Group read_group_metadata(const json& jgroup) val.pixel_size = jgroup["pixel-size"]; if (jgroup.contains("mirrored")) val.mirrored = !!jgroup["mirrored"]; + if (jgroup.contains("from-rotation") && !jgroup["from-rotation"].is_null()) + val.from_rotation = direction_index_from_name(jgroup["from-rotation"]); val.is_defined = true; return val; @@ -278,8 +263,6 @@ void write_all_frames(json& jroot, ArrayView<const Frame> array) void write_group_metadata(json& jgroup, const Group& val) { - constexpr Group group_defaults; - fm_assert(jgroup.is_null()); fm_assert(val.is_defined); @@ -296,6 +279,8 @@ void write_group_metadata(json& jgroup, const Group& val) jgroup["tint-add"] = val.tint_add; } jgroup["mirrored"] = val.mirrored; + if (val.from_rotation != (uint8_t )-1) + jgroup["from-rotation"] = direction_index_to_name(val.from_rotation); } void write_direction_metadata(json& jdir, const Direction& dir) diff --git a/serialize/wall-atlas.hpp b/serialize/wall-atlas.hpp index 725204ad..febdf583 100644 --- a/serialize/wall-atlas.hpp +++ b/serialize/wall-atlas.hpp @@ -14,9 +14,6 @@ namespace floormat::Wall::detail { using nlohmann::json; -uint8_t direction_index_from_name(StringView s); -StringView direction_index_to_name(size_t i); - [[nodiscard]] std::vector<Frame> read_all_frames(const json& jroot); [[nodiscard]] Group read_group_metadata(const json& jgroup); [[nodiscard]] Direction read_direction_metadata(const json& jroot, Direction_ dir); diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp index 2486eafd..90d5dfe7 100644 --- a/src/wall-atlas.cpp +++ b/src/wall-atlas.cpp @@ -7,6 +7,57 @@ #include <Magnum/ImageView.h> #include <Magnum/GL/TextureFormat.h> +namespace floormat::Wall { + +uint8_t direction_index_from_name(StringView s) noexcept(false) +{ + for (uint8_t i = 0; auto [n, _] : wall_atlas::directions) + if (n == s) + return i; + else + i++; + + fm_throw("bad rotation name '{}'"_cf, s); +} + +StringView direction_index_to_name(size_t i) noexcept(false) +{ + fm_soft_assert(i < arraySize(wall_atlas::directions)); + return wall_atlas::directions[i].name; +} + +void resolve_wall_rotations(std::vector<Wall::Direction>& array, const std::array<DirArrayIndex, Direction_COUNT>& map) noexcept(false) +{ + for (auto [dir_name, dir] : wall_atlas::directions) + { + auto DAI = map[(size_t)dir]; + if (!DAI) + continue; + auto& D = array[DAI.val]; + for (auto [group_name, ptr, gr] : Direction::groups) + { + auto& G = D.*ptr; + if (!G.is_defined) + continue; + if (G.from_rotation != (uint8_t)-1) + { + const auto& DAI2 = map[G.from_rotation]; + if (!DAI2) + fm_throw("from_rotation for '{}/{}' points to nonexistent rotation {}"_cf, + dir_name, group_name, direction_index_to_name(G.from_rotation)); + const auto& D2 = array[DAI2.val]; + const auto& G2 = D2.*ptr; + if (!G2.is_defined) + fm_throw("from_rotation for '{}/{}' points to empty group '{}/{}'"_cf, + dir_name, group_name, direction_index_to_name(G.from_rotation), group_name); + G.from_rotation = DAI2.val; + } + } + } +} + +} // namespace floormat::Wall + namespace floormat { using namespace floormat::Wall; @@ -74,7 +125,7 @@ wall_atlas::wall_atlas(wall_atlas_def def, String path, const ImageView2D& img) for (auto [group_name, gmemb, gr] : Direction::groups) { const auto& G = D->*gmemb; - fm_soft_assert(!G.is_defined == !G.count); + fm_soft_assert(G.is_defined == !!G.count); fm_soft_assert(G.is_defined == (G.index != (uint32_t)-1)); if (!G.is_defined) continue; @@ -92,6 +143,8 @@ wall_atlas::wall_atlas(wall_atlas_def def, String path, const ImageView2D& img) fm_throw("wall_atlas '{}' is empty!"_cf, _path); } + resolve_wall_rotations(_dir_array, _direction_map); + _texture.setLabel(_path) .setWrapping(GL::SamplerWrapping::ClampToEdge) .setMagnificationFilter(GL::SamplerFilter::Nearest) diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp index fa3006fc..1f18489a 100644 --- a/src/wall-atlas.hpp +++ b/src/wall-atlas.hpp @@ -15,6 +15,9 @@ namespace floormat { class wall_atlas; } namespace floormat::Wall { +uint8_t direction_index_from_name(StringView s) noexcept(false); +StringView direction_index_to_name(size_t i) noexcept(false); + struct Frame { Vector2ui offset = { (unsigned)-1, (unsigned)-1 }, size; @@ -28,6 +31,7 @@ struct Group Vector2ui pixel_size; Color4 tint_mult{1,1,1,1}; Color3 tint_add{}; + uint8_t from_rotation = (uint8_t)-1; bool mirrored : 1 = false, default_tint : 1 = true, is_defined : 1 = false; @@ -73,11 +77,13 @@ struct Info struct DirArrayIndex { uint8_t val = (uint8_t)-1; - operator bool() const { return val != (uint8_t)-1; } + explicit operator bool() const { return val != (uint8_t)-1; } bool operator==(const DirArrayIndex&) const noexcept; }; +void resolve_wall_rotations(std::vector<Wall::Direction>& dirs, const std::array<DirArrayIndex, Direction_COUNT>& map) noexcept(false); + } // namespace floormat::Wall namespace floormat { diff --git a/test/json/wall-atlas-02_groups.json b/test/json/wall-atlas-02_groups.json index c9617d4f..b2d44fc5 100644 --- a/test/json/wall-atlas-02_groups.json +++ b/test/json/wall-atlas-02_groups.json @@ -22,6 +22,13 @@ "wall": { "offset": 0, "count": 1 + }, + "corner-L": { + "offset": 0, + "count": 11 + }, + "top": { + "from-rotation": "w" } }, "w": { @@ -40,7 +47,7 @@ "top": { "pixel-size": "192 x 42", "offset": 1, - "count": 2 + "count": 12 }, "corner-L": { "from-rotation": "n" } } diff --git a/test/wall-atlas.cpp b/test/wall-atlas.cpp index 33b5d1fe..d6b0f564 100644 --- a/test/wall-atlas.cpp +++ b/test/wall-atlas.cpp @@ -74,6 +74,31 @@ void test_read_groups(StringView filename) fm_assert(dir == dir2); } +void test_from_rotation(StringView filename) +{ + const auto path = Path::join(json_path(), filename); + auto atlas = wall_atlas_def::deserialize(path); + auto DAI_n = atlas.direction_map[(size_t)Direction_::N]; + auto DAI_w = atlas.direction_map[(size_t)Direction_::W]; + fm_assert(DAI_n); fm_assert(DAI_w); + const auto& D_n = atlas.direction_array[DAI_n.val]; + const auto& D_w = atlas.direction_array[DAI_w.val]; + constexpr auto null = (uint8_t)-1; + resolve_wall_rotations(atlas.direction_array, atlas.direction_map); + fm_assert(!D_n.corner_R.is_defined && D_n.corner_R.from_rotation == null); + fm_assert(D_n.top.is_defined); + fm_assert(D_n.top.from_rotation != null); + fm_assert(D_n.top.from_rotation != null); + fm_assert(D_w.top.from_rotation == null); + fm_assert(D_w.top.is_defined); + fm_assert(D_n.corner_L.is_defined); + fm_assert(D_n.corner_L.from_rotation == null); + fm_assert(D_w.corner_L.is_defined); + fm_assert(D_w.corner_L.from_rotation == DAI_n.val); + fm_assert(atlas.direction_array[D_w.corner_L.from_rotation].corner_L.count == 11); + fm_assert(atlas.direction_array[D_n.top.from_rotation].top.count == 12); +} + [[nodiscard]] wall_atlas_def read_and_check(StringView filename) { auto atlas = wall_atlas_def::deserialize(filename); @@ -112,6 +137,7 @@ void test_expected_size() void floormat::test_app::test_wall_atlas() { using namespace floormat::Wall::detail; + using namespace floormat::Wall; { test_expected_size(); @@ -125,6 +151,7 @@ void floormat::test_app::test_wall_atlas() { test_read_header(S_02_groups_json); test_read_groups(S_02_groups_json); + test_from_rotation(S_02_groups_json); } { auto a = read_and_check(Path::join(json_path(), S_02_groups_json)); |