summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--serialize/corrade-string.cpp8
-rw-r--r--serialize/corrade-string.hpp1
-rw-r--r--serialize/scenery.cpp120
-rw-r--r--serialize/scenery.hpp31
-rw-r--r--src/scenery.cpp21
-rw-r--r--src/scenery.hpp15
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);