diff options
-rw-r--r-- | serialize/corrade-string.cpp | 8 | ||||
-rw-r--r-- | serialize/corrade-string.hpp | 1 | ||||
-rw-r--r-- | serialize/scenery.cpp | 120 | ||||
-rw-r--r-- | serialize/scenery.hpp | 31 | ||||
-rw-r--r-- | src/scenery.cpp | 21 | ||||
-rw-r--r-- | src/scenery.hpp | 15 |
6 files changed, 179 insertions, 17 deletions
diff --git a/serialize/corrade-string.cpp b/serialize/corrade-string.cpp index 16ae23e1..7b772d4c 100644 --- a/serialize/corrade-string.cpp +++ b/serialize/corrade-string.cpp @@ -28,4 +28,12 @@ void adl_serializer<StringView>::to_json(json& j, StringView val) to_json(j, s); } +void adl_serializer<StringView>::from_json(const json& j, StringView& val) +{ + using nlohmann::from_json; + std::string_view s; + from_json(j, s); + val = StringView{s.data(), s.size()}; +} + } // namespace nlohmann diff --git a/serialize/corrade-string.hpp b/serialize/corrade-string.hpp index 81922367..6cfd8472 100644 --- a/serialize/corrade-string.hpp +++ b/serialize/corrade-string.hpp @@ -13,6 +13,7 @@ struct adl_serializer<Corrade::Containers::String> { template<> struct adl_serializer<Corrade::Containers::StringView> { static void to_json(json& j, Corrade::Containers::StringView val); + static void from_json(const json& j, Corrade::Containers::StringView& val); }; } // namespace nlohmann diff --git a/serialize/scenery.cpp b/serialize/scenery.cpp new file mode 100644 index 00000000..b2490739 --- /dev/null +++ b/serialize/scenery.cpp @@ -0,0 +1,120 @@ +#include "scenery.hpp" +#include "anim-atlas.hpp" +#include "compat/assert.hpp" +#include "loader/loader.hpp" +#include "serialize/corrade-string.hpp" +#include <array> +#include <Corrade/Containers/StringStlView.h> +#include <nlohmann/json.hpp> + +namespace { + +using namespace floormat; + +constexpr struct { + scenery_type value = scenery_type::none; + StringView str; +} scenery_type_map[] = { + { scenery_type::none, "none"_s }, + { scenery_type::generic, "generic"_s }, + { scenery_type::door, "door"_s }, + { scenery_type::object, "object"_s }, +}; + +constexpr struct { + rotation value = rotation::N; + StringView str; +} rotation_map[] = { + { rotation::N, "n"_s }, + { rotation::NE, "ne"_s }, + { rotation::E, "e"_s }, + { rotation::SE, "se"_s }, + { rotation::S, "s"_s }, + { rotation::SW, "sw"_s }, + { rotation::W, "w"_s }, + { rotation::NW, "nw"_s }, +}; + +template<std::size_t N, typename T> +auto foo_from_string(StringView str, const T(&map)[N], const char* desc) +{ + for (const auto& [value, str2] : map) + if (str2 == str) + return value; + fm_abort("wrong %s string '%s'", desc, str.data()); +} + +template<std::size_t N, typename T> +StringView foo_to_string(auto type, const T(&map)[N], const char* desc) +{ + for (const auto& [type2, str] : map) + if (type2 == type) + return str; + fm_abort("wrong %s enum '%hhu'", desc, type); +} + +} // namespace + +namespace floormat { + +} // namespace floormat + +namespace nlohmann { + +void adl_serializer<scenery_type>::to_json(json& j, const scenery_type val) +{ + j = foo_to_string(val, scenery_type_map, "scenery_type"); +} + +void adl_serializer<scenery_type>::from_json(const json& j, scenery_type& val) +{ + val = foo_from_string(j, scenery_type_map, "scenery_type"); +} + +void adl_serializer<rotation>::to_json(json& j, const rotation val) +{ + j = foo_to_string(val, rotation_map, "rotation"); +} + +void adl_serializer<rotation>::from_json(const json& j, rotation& val) +{ + val = foo_from_string(j, rotation_map, "rotation"); +} + +void adl_serializer<scenery_proto>::to_json(json& j, const scenery_proto& val) +{ + const scenery& f = val.frame; + j["type"] = f.type; + fm_assert(val.atlas); + j["atlas-name"] = val.atlas->name(); + fm_assert(f.frame != scenery::NO_FRAME); + j["frame"] = f.frame; + j["rotation"] = f.r; + j["passable"] = f.passable; + j["blocks-view"] = f.blocks_view; + j["active"] = f.active; +} + +void adl_serializer<scenery_proto>::from_json(const json& j, scenery_proto& val) +{ + auto& f = val.frame; + f.type = j["type"]; + StringView atlas_name = j["atlas-name"]; + val.atlas = loader.anim_atlas(atlas_name); + f = {}; + if (j.contains("frame")) + f.frame = j["frame"]; + if (j.contains("animated")) + f.animated = j["animated"]; + fm_assert(f.animated == (f.frame == scenery::NO_FRAME)); + if (j.contains("rotation")) + f.r = j["rotation"]; + if (j.contains("passable")) + f.passable = j["passable"]; + if (j.contains("blocks-view")) + f.blocks_view = j["blocks-view"]; + if (j.contains("active")) + f.active = j["active"]; +} + +} // namespace nlohmann diff --git a/serialize/scenery.hpp b/serialize/scenery.hpp new file mode 100644 index 00000000..e7946913 --- /dev/null +++ b/serialize/scenery.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "src/scenery.hpp" +#include <Corrade/Containers/StringView.h> +#include <vector> +#include <nlohmann/json_fwd.hpp> + +namespace nlohmann { + +template<> struct adl_serializer<floormat::scenery_type> { + static void to_json(json& j, floormat::scenery_type val); + static void from_json(const json& j, floormat::scenery_type& val); +}; + +template<> struct adl_serializer<floormat::rotation> { + static void to_json(json& j, floormat::rotation val); + static void from_json(const json& j, floormat::rotation& val); +}; + +template<> struct adl_serializer<floormat::scenery_proto> { + static void to_json(json& j, const floormat::scenery_proto& val); + static void from_json(const json& j, floormat::scenery_proto& val); + + struct item { + Corrade::Containers::StringView name, description; + floormat::scenery_proto proto; + }; + + static std::vector<item> deserialize_list(Corrade::Containers::StringView file); +}; + +} // namespace nlohmann diff --git a/src/scenery.cpp b/src/scenery.cpp index eb90b598..03adc39e 100644 --- a/src/scenery.cpp +++ b/src/scenery.cpp @@ -12,7 +12,7 @@ scenery_proto::scenery_proto(const std::shared_ptr<anim_atlas>& atlas, const sce {} scenery_proto::scenery_proto(scenery::generic_tag_t, rotation r, const std::shared_ptr<anim_atlas>& atlas, bool passable, scenery::frame_t frame) : - atlas{atlas}, frame{scenery::generic, r, *atlas, passable, frame} + atlas{atlas}, frame{scenery::generic, r, *atlas, frame, passable} {} scenery_proto::scenery_proto(scenery::door_tag_t, rotation r, const std::shared_ptr<anim_atlas>& atlas, bool is_open) : @@ -39,19 +39,19 @@ scenery_ref::operator bool() const noexcept { return atlas != nullptr; } scenery::scenery() noexcept : scenery{none_tag_t{}} {} scenery::scenery(none_tag_t) noexcept : passable{true} {} -scenery::scenery(generic_tag_t, rotation r, const anim_atlas& atlas, bool passable, frame_t frame) : - frame{frame}, r{r}, passable{passable}, type{scenery_type::generic} +scenery::scenery(generic_tag_t, rotation r, const anim_atlas& atlas, frame_t frame, + bool passable, bool blocks_view, bool animated, bool active) : + frame{frame}, r{r}, passable{passable}, + blocks_view{blocks_view}, active{active}, animated{animated}, + type{scenery_type::generic} { fm_assert(frame < atlas.group(r).frames.size()); } scenery::scenery(door_tag_t, rotation r, const anim_atlas& atlas, bool is_open) : frame{frame_t(is_open ? 0 : atlas.group(r).frames.size()-1)}, - r{r}, passable{is_open}, type{scenery_type::door} -{} - -scenery::scenery(float dt, frame_t frame, rotation r, bool passable, scenery_type type) : - delta{dt}, frame{frame}, r{r}, passable{passable}, type{type} + r{r}, + passable{is_open}, blocks_view{!is_open}, type{scenery_type::door} {} bool scenery::can_activate() const noexcept @@ -63,10 +63,10 @@ bool scenery::can_activate() const noexcept { default: return false; - case scenery_type::door: - return !active; case scenery_type::object: return true; + case scenery_type::door: + return !active; } #endif } @@ -96,6 +96,7 @@ void scenery::update(float dt, const anim_atlas& anim) const int fr = frame + dir*n; active = fr > 0 && fr < nframes-1; passable = fr <= 0; + blocks_view = !passable; frame = (frame_t)std::clamp(fr, 0, nframes-1); if (!active) delta = 0; diff --git a/src/scenery.hpp b/src/scenery.hpp index aabf7315..c1e2b5ea 100644 --- a/src/scenery.hpp +++ b/src/scenery.hpp @@ -31,17 +31,18 @@ struct scenery final float delta = 0; frame_t frame = NO_FRAME; - rotation r : 3 = rotation::N; - std::uint8_t passable : 1 = false; - std::uint8_t active : 1 = false; - std::uint8_t closing : 1 = true; - scenery_type type : 2 = scenery_type::none; + rotation r : 3 = rotation::N; + std::uint8_t passable : 1 = false; + std::uint8_t blocks_view : 1 = false; // todo + std::uint8_t active : 1 = false; + std::uint8_t closing : 1 = false; + std::uint8_t animated : 1 = false; // todo + scenery_type type : 3 = scenery_type::none; scenery() noexcept; scenery(none_tag_t) noexcept; - scenery(generic_tag_t, rotation r, const anim_atlas& atlas, bool passable = false, frame_t frame = 0); + scenery(generic_tag_t, rotation r, const anim_atlas& atlas, frame_t frame = 0, bool passable = false, bool blocks_view = false, bool animated = false, bool active = false); scenery(door_tag_t, rotation r, const anim_atlas& atlas, bool is_open = false); - scenery(float dt, frame_t frame, rotation r, bool passable, scenery_type type); bool can_activate() const noexcept; bool activate(const anim_atlas& atlas); |