diff options
Diffstat (limited to 'serialize/wall-atlas.cpp')
-rw-r--r-- | serialize/wall-atlas.cpp | 95 |
1 files changed, 84 insertions, 11 deletions
diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp index 5db79e05..3749be64 100644 --- a/serialize/wall-atlas.cpp +++ b/serialize/wall-atlas.cpp @@ -1,11 +1,16 @@ #include "wall-atlas.hpp" #include "magnum-vector2i.hpp" #include "magnum-vector.hpp" +#include "corrade-string.hpp" #include "compat/exception.hpp" +#include "loader/loader.hpp" #include <utility> #include <string_view> +#include <Corrade/Containers/PairStl.h> #include <Corrade/Containers/StringStl.h> #include <Corrade/Containers/StringStlView.h> +#include <Magnum/ImageView.h> +#include <Magnum/Trade/ImageData.h> #include <nlohmann/json.hpp> // todo add test on dummy files that generates 100% coverage on the j.contains() blocks! @@ -31,6 +36,27 @@ StringView direction_index_to_name(size_t i) return wall_atlas::directions[i].name; } +Array<Frame> read_all_frames(const json& jroot) +{ + fm_assert(jroot.contains("frames"sv)); + + Array<Frame> frames; + const auto& jframes = jroot["frames"sv]; + + fm_assert(jframes.is_array()); + const auto sz = jframes.size(); + frames = Array<Frame>{sz}; + + for (auto i = 0uz; i < sz; i++) + { + const auto& jframe = jframes[i]; + fm_assert(jframe.is_object()); + frames[i] = jframe; + } + + return frames; +} + Group read_group_metadata(const json& jgroup) { fm_assert(jgroup.is_object()); @@ -40,11 +66,10 @@ Group read_group_metadata(const json& jgroup) { int count = 0, index = -1; bool has_count = jgroup.contains("count"sv) && (count = jgroup["count"sv]) != 0, - has_index = jgroup.contains("offset"sv); - if (has_index) - index = jgroup["offset"sv]; + has_index = jgroup.contains("offset"sv) && (index = jgroup["offset"sv]) != -1; fm_soft_assert(has_count == has_index); fm_soft_assert(!has_index || index >= 0 && index < 1 << 20); + fm_soft_assert(count >= 0); // todo check index within range } @@ -86,6 +111,23 @@ Direction read_direction_metadata(const json& jroot, Direction_ dir) return val; } +Pair<Array<Direction>, std::array<DirArrayIndex, 4>> read_all_directions(const json& jroot) +{ + size_t count = 0; + for (auto [str, _] : wall_atlas::directions) + if (jroot.contains(str)) + count++; + Array<Direction> array{count}; + std::array<DirArrayIndex, 4> map = {}; + for (uint8_t i = 0; auto [str, dir] : wall_atlas::directions) + if (jroot.contains(str)) + { + map[(size_t)dir] = {.val = i}; + array[i++] = read_direction_metadata(jroot, dir); + } + return { std::move(array), std::move(map) }; +} + Info read_info_header(const json& jroot) { fm_soft_assert(jroot.contains(("name"sv))); @@ -97,12 +139,26 @@ Info read_info_header(const json& jroot) return val; } +void write_all_frames(json& jroot, ArrayView<const Frame> array) +{ + auto jframes = json{json::value_t::array}; + for (const Frame& frame : array) + { + json jframe = frame; + jframes.push_back(std::move(jframe)); + } + jroot["frames"sv] = std::move(jframes); +} + void write_group_metadata(json& jgroup, const Group& val) { fm_assert(jgroup.is_object()); - fm_assert(jgroup.empty()); - jgroup["offset"sv] = val.index; + if (val.index != (uint32_t)-1) + jgroup["offset"sv] = val.index; + else + jgroup["offset"sv] = -1; + jgroup["count"sv] = val.count; jgroup["pixel-size"sv] = val.pixel_size; jgroup["tint-mult"sv] = Vector4(val.tint_mult); @@ -114,8 +170,6 @@ void write_group_metadata(json& jgroup, const Group& val) void write_direction_metadata(json& jdir, const Direction& dir) { - //auto name = std::string_view{direction_index_to_name((size_t)i)}; - for (auto [s_, memfn, tag] : Direction::members) { std::string_view s = s_; @@ -138,14 +192,13 @@ void write_all_directions(json& jroot, const wall_atlas& a) { auto jdir = json{json::value_t::object}; write_direction_metadata(jdir, *dir); - jroot[name] = jdir; + jroot[name] = std::move(jdir); } } } void write_info_header(json& jroot, const Info& info) -{ - jroot["name"sv] = info.name; +{ jroot["name"sv] = info.name; if (info.description) jroot["description"sv] = info.description; jroot["depth"sv] = info.depth; @@ -153,21 +206,41 @@ void write_info_header(json& jroot, const Info& info) } // namespace floormat::Wall::detail +namespace floormat::Wall { + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Frame, offset) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Info, name, description, depth) + +} // namespace floormat::Wall + namespace nlohmann { using namespace floormat; +using namespace floormat::Wall; using namespace floormat::Wall::detail; +void adl_serializer<Frame>::to_json(nlohmann::json& j, const Frame& x) { using nlohmann::to_json; to_json(j, x); } +void adl_serializer<Frame>::from_json(const json& j, Frame& x) { using nlohmann::from_json; from_json(j, x); } + void adl_serializer<std::shared_ptr<wall_atlas>>::to_json(json& j, const std::shared_ptr<const wall_atlas>& x) { fm_assert(x != nullptr); write_info_header(j, x->info()); write_all_directions(j, *x); + write_all_frames(j, x->raw_frame_array()); } void adl_serializer<std::shared_ptr<wall_atlas>>::from_json(const json& j, std::shared_ptr<wall_atlas>& x) { - + auto info = read_info_header(j); + fm_assert(loader.check_atlas_name(info.name)); + auto [dirs, map] = read_all_directions(j); + Array<Frame> frames; + auto img = loader.texture(loader.WALL_TILESET_PATH, info.name); + if (j.contains("frames"sv)) + frames = read_all_frames(j); + + x = std::make_shared<wall_atlas>(std::move(info), img, std::move(frames), std::move(dirs), map); } } // namespace nlohmann |