diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-11-05 07:39:06 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-11-05 07:39:06 +0100 |
commit | 98da53beb78d9a617a1c66b404e9a7d8469a443a (patch) | |
tree | e708c5133ea5705d402b31b16aadcb24ec25b6c1 | |
parent | 8cd318bc55e9d1588307999618a0d8bef09f9f68 (diff) |
a
-rw-r--r-- | serialize/wall-atlas.cpp | 69 | ||||
-rw-r--r-- | serialize/wall-atlas.hpp | 6 | ||||
-rw-r--r-- | src/wall-atlas.cpp | 50 | ||||
-rw-r--r-- | src/wall-atlas.hpp | 40 | ||||
-rw-r--r-- | test/CMakeLists.txt | 6 | ||||
-rw-r--r-- | test/json/frameset-header.json | 9 | ||||
-rw-r--r-- | test/wall-atlas.cpp | 38 | ||||
-rw-r--r-- | wall-tileset-tool/main.cpp | 13 |
8 files changed, 185 insertions, 46 deletions
diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp index d8fe8f60..23fbf1b3 100644 --- a/serialize/wall-atlas.cpp +++ b/serialize/wall-atlas.cpp @@ -3,6 +3,7 @@ #include "magnum-vector.hpp" #include "compat/exception.hpp" #include <utility> +#include <string_view> #include <Corrade/Containers/StringStl.h> #include <nlohmann/json.hpp> @@ -26,18 +27,22 @@ size_t rotation_from_name(StringView s) fm_throw("bad rotation name '{}'"_cf, fmt::string_view{s.data(), s.size()}); } -void read_frameset_metadata(const nlohmann::json& j, wall_frames& val) +StringView rotation_to_name(size_t i) { + fm_soft_assert(i < std::size(rotation_names)); + return rotation_names[i]; +} + +void read_frameset_metadata(const nlohmann::json& j, wall_frames& val, size_t& rot) +{ + val = {}; + rot = rotation_from_name(std::string{j["name"s]}); + if (j.contains("pixel-size"s)) val.pixel_size = j["pixel-size"s]; if (j.contains("tint"s)) { - auto& t = j["tint"s]; - fm_soft_assert(t.contains("mult"s) || t.contains("add"s)); - if (t.contains("mult"s)) - val.tint_mult = Vector4(t["mult"s]); - if (t.contains("add"s)) - val.tint_add = Vector3(t["add"s]); + std::tie(val.tint_mult, val.tint_add) = std::pair<Vector4, Vector3>{j["tint"s]}; fm_soft_assert(val.tint_mult >= Color4{0}); } if (j.contains("from-rotation"s)) @@ -48,17 +53,15 @@ void read_frameset_metadata(const nlohmann::json& j, wall_frames& val) val.use_default_tint = j["use-default-tint"s]; } -void write_frameset_metadata(nlohmann::json& j, const wall_atlas& a, const wall_frames& val) +void write_frameset_metadata(nlohmann::json& j, const wall_atlas& a, const wall_frames& val, size_t rot) { constexpr wall_frames default_value; -#if 0 - fm_soft_assert(val.index != default_value.index); - fm_soft_assert(val.count != default_value.count); - fm_soft_assert(val.pixel_size != default_value.pixel_size); -#endif - - fm_soft_assert(val.index < a.array().size()); - fm_soft_assert(val.count != (uint32_t)-1 && val.count > 0); + + fm_soft_assert(val.count != (uint32_t)-1); + fm_soft_assert(val.index == (uint32_t)-1 || val.index < a.frame_array().size()); + fm_soft_assert((val.index == (uint32_t)-1) == (val.count == 0)); + + j["name"s] = rotation_to_name(rot); j["pixel-size"s] = val.pixel_size; if (val.tint_mult != default_value.tint_mult || val.tint_add != default_value.tint_add) { @@ -77,8 +80,42 @@ void write_frameset_metadata(nlohmann::json& j, const wall_atlas& a, const wall_ j["use-default-tint"s] = true; } +void read_framesets(const nlohmann::json& jf, wall_atlas_def& val) +{ + fm_soft_assert(jf.is_object()); + fm_soft_assert(val.framesets == nullptr && val.frameset_count == 0); + uint8_t count = 0; + + static_assert(std::size(rotation_names) == 4); + for (auto i = 0uz; i < 4; i++) + { + const auto& r = rotation_names[i]; + auto key = std::string_view{r.data(), r.size()}; + if (jf.contains(key)) + { + fm_soft_assert(jf[key].is_object()); + auto& index = val.frameset_indexes[i]; + fm_soft_assert(index == (uint8_t)-1); + index = count++; + } + } + fm_soft_assert(count > 0); + fm_soft_assert(count == jf.size()); + + val.framesets = std::make_unique<wall_frame_set[]>(count); + val.frameset_count = count; +} + } // namespace +void Serialize::wall_test::read_atlas_header(const nlohmann::json& j, wall_atlas_def& val) +{ + val = {}; + val.info = { std::string(j["name"s]), j["depth"], }; + val.frame_count = (uint32_t)j["frames"s].size(); + read_framesets(j["framesets"s], val); +} + } // namespace floormat namespace nlohmann { diff --git a/serialize/wall-atlas.hpp b/serialize/wall-atlas.hpp index 5e454f87..f8f3110b 100644 --- a/serialize/wall-atlas.hpp +++ b/serialize/wall-atlas.hpp @@ -13,3 +13,9 @@ struct adl_serializer<std::shared_ptr<floormat::wall_atlas>> }; } // namespace nlohmann + +namespace floormat::Serialize::wall_test { + +void read_atlas_header(const nlohmann::json& j, wall_atlas_def& val); + +} // namespace floormat::Serialize::wall_test diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp index 685125cd..be4010c7 100644 --- a/src/wall-atlas.cpp +++ b/src/wall-atlas.cpp @@ -8,6 +8,7 @@ namespace floormat { 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); @@ -16,19 +17,27 @@ size_t wall_atlas::enum_to_index(enum rotation r) } wall_atlas::wall_atlas(wall_info info, const ImageView2D& image, - ArrayView<const wall_frame_set> rotations, - ArrayView<const wall_frame> frames) : - _array{NoInit, frames.size()}, _info(std::move(info)) + 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} { - fm_assert(info.depth > 0); - fm_assert(rotations.size() <= _rotations.size()); - _rotation_count = (uint8_t)rotations.size(); - for (auto i = 0uz; const auto& fr : frames) - _array[i++] = fr; - for (auto i = 0uz; const auto& r : rotations) - _rotations[i++] = r; - - _texture.setLabel(_name) + { 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) @@ -40,16 +49,21 @@ wall_atlas::wall_atlas(wall_info info, const ImageView2D& image, wall_atlas::wall_atlas() = default; wall_atlas::~wall_atlas() noexcept = default; -const wall_frame_set& wall_atlas::frameset(size_t i) const { return _rotations[i]; } -const wall_frame_set& wall_atlas::frameset(enum rotation r) const { return frameset(enum_to_index(r)); } -const ArrayView<const wall_frame> wall_atlas::array() const { return _array; } +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)); } + +const wall_frame_set& wall_atlas::frameset(size_t i) const +{ + fm_assert(i < 4 && _frameset_indexes[i] != (uint8_t)-1); + return _framesets[i]; +} ArrayView<const wall_frame> wall_frames::items(const wall_atlas& a) const { - fm_assert(index < a.array().size()); - fm_debug_assert(count != (uint32_t)-1); - return { a.array() + index, count }; + auto sz = a.frame_array().size(); (void)sz; + fm_assert(index < sz && index + count <= sz); + return { a.frame_array() + index, count }; } } // namespace floormat diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp index 4414ac3f..aa18c0bc 100644 --- a/src/wall-atlas.hpp +++ b/src/wall-atlas.hpp @@ -1,6 +1,8 @@ #pragma once +#include "compat/defs.hpp" #include "src/rotation.hpp" #include <array> +#include <memory> #include <Corrade/Containers/Array.h> #include <Corrade/Containers/String.h> #include <Magnum/Math/Vector2.h> @@ -20,7 +22,7 @@ struct wall_frames { ArrayView<const wall_frame> items(const wall_atlas& a) const; - uint32_t index = (uint32_t)-1, count = (uint32_t)-1; // not serialized + uint32_t index = (uint32_t)-1, count = 0; Vector2ui pixel_size; Color4 tint_mult{1,1,1,1}; @@ -39,30 +41,44 @@ struct wall_frame_set struct wall_info { String name = "(unnamed)"_s; - float depth = 1; + 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 wall_atlas final { + fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(wall_atlas); wall_atlas(); - wall_atlas(wall_info info, - const ImageView2D& image, - ArrayView<const wall_frame_set> rotations, - ArrayView<const wall_frame> frames); ~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; - const ArrayView<const wall_frame> array() const; + ArrayView<const wall_frame> frame_array() const; StringView name() const; private: - String _name; - std::array<wall_frame_set, 4> _rotations; - Array<wall_frame> _array; - GL::Texture2D _texture; + std::unique_ptr<wall_frame_set[]> _framesets; + Array<wall_frame> _frame_array; wall_info _info; - uint8_t _rotation_count = 0; + GL::Texture2D _texture; + std::array<uint8_t, 4> _frameset_indexes; + uint8_t _frameset_count = 0; }; } // namespace floormat diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2c1ce2ff..897268f3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -26,3 +26,9 @@ file(GLOB files "save/*.dat" CONFIGURE_ARGS) foreach(file ${files}) install(FILES "${file}" DESTINATION "${save-dir}") endforeach() + +set(json-dir "${CMAKE_BINARY_DIR}/test/json") +file(GLOB files "json/*.json" CONFIGURE_ARGS) +foreach(file ${files}) + install(FILES "${file}" DESTINATION "${json-dir}") +endforeach() diff --git a/test/json/frameset-header.json b/test/json/frameset-header.json new file mode 100644 index 00000000..8b32cabc --- /dev/null +++ b/test/json/frameset-header.json @@ -0,0 +1,9 @@ +{ + "name": "foo", + "depth": 42, + "framesets": { + "w": {}, + "n": {} + }, + "frames": [] +} diff --git a/test/wall-atlas.cpp b/test/wall-atlas.cpp index 61f252b7..b1cdd8d6 100644 --- a/test/wall-atlas.cpp +++ b/test/wall-atlas.cpp @@ -1,16 +1,54 @@ #include "test/app.hpp" #include "src/wall-atlas.hpp" +#include "serialize/wall-atlas.hpp" +#include "serialize/json-helper.hpp" +#include "loader/loader.hpp" +#include <algorithm> +#include <Corrade/Utility/Path.h> namespace floormat { +namespace ranges = std::ranges; +namespace test = floormat::Serialize::wall_test; + namespace { +void test_atlas_header(StringView path) +{ + auto j = json_helper::from_json_(Path::join(path, "frameset-header.json"_s)); + wall_atlas_def def; + test::read_atlas_header(j, def); + + fm_assert(def.info.name == "foo"_s); + fm_assert(def.info.depth == 42); + fm_assert(def.frameset_count == 2); + + constexpr auto none = (uint8_t)-1; + enum : uint8_t { N, E, S, W, }; + + fm_assert(def.frameset_indexes[N] == 0 || def.frameset_indexes[N] == 1); + fm_assert(def.frameset_indexes[E] == none); + fm_assert(def.frameset_indexes[S] == none); + if (def.frameset_indexes[N] == 0) + fm_assert(def.frameset_indexes[W] == 1); + else if (def.frameset_indexes[N] == 1) + fm_assert(def.frameset_indexes[W] == 0); + + std::fputs("", stdout); +} } // namespace void test_app::test_wall_atlas() { + fm_assert(Path::exists(Path::join(loader.TEMP_PATH, "CMakeCache.txt"))); + const auto path = Path::join(loader.TEMP_PATH, "test/json"_s); + fm_assert(Path::isDirectory(path)); + + test_atlas_header(path); } + + } // namespace floormat diff --git a/wall-tileset-tool/main.cpp b/wall-tileset-tool/main.cpp index 511ef4c2..5863bdf4 100644 --- a/wall-tileset-tool/main.cpp +++ b/wall-tileset-tool/main.cpp @@ -11,6 +11,7 @@ #include <Corrade/Containers/TripleStl.h> #include <Corrade/Utility/Path.h> #include <Corrade/Utility/Arguments.h> +#include <nlohmann/json.hpp> #include <opencv2/core/mat.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/imgcodecs/imgcodecs.hpp> @@ -22,6 +23,18 @@ using namespace std::string_literals; namespace { +wall_atlas_def read_atlas_def(const nlohmann::json& j) +{ + auto val = wall_atlas_def{}; + auto& info = val.info; + info.name = std::string(j["name"s]); + info.depth = j["depth"s]; + + fm_assert(loader.check_atlas_name(info.name)); + + return val; +} + struct options { String input_dir, input_file, output_dir; |