summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-12-02 14:44:32 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-12-02 14:46:59 +0100
commit889d2c0c0933cf2fd9e068b1d2b79eb936b29b58 (patch)
treecfc5f5b6e417c28482734645a69e0d49388fa5b3
parent8dbf450e34121358992e48212ae22cb7f5fc92f9 (diff)
src, serialize: work on pass mode
1. add one more value to the enum 2. serialize it properly in binary 3. serialize it as string in json
-rw-r--r--editor/update.cpp2
-rw-r--r--scenery/scenery.json3
-rw-r--r--serialize/pass-mode.cpp44
-rw-r--r--serialize/pass-mode.hpp13
-rw-r--r--serialize/scenery.cpp13
-rw-r--r--serialize/world-impl.hpp3
-rw-r--r--serialize/world-reader.cpp15
-rw-r--r--serialize/world-writer.cpp7
-rw-r--r--src/pass-mode.hpp10
-rw-r--r--src/scenery.cpp17
-rw-r--r--src/scenery.hpp6
-rw-r--r--src/tile.cpp11
-rw-r--r--src/tile.hpp10
13 files changed, 112 insertions, 42 deletions
diff --git a/editor/update.cpp b/editor/update.cpp
index b78175f9..ad4fb355 100644
--- a/editor/update.cpp
+++ b/editor/update.cpp
@@ -32,7 +32,7 @@ void app::maybe_initialize_chunk_(const chunk_coords& pos, chunk& c)
c[{K+1, K }].wall_west() = { _wall2, 0 };
c[{K+3, K+1}].scenery() = { scenery::door, _door, rotation::N, };
c[{ 3, 4 }].scenery() = { scenery::generic, _table, rotation::W, };
- c[{K, K+1}].scenery() = { scenery::generic, _control_panel, rotation::N, scenery::frame_t{0}, true };
+ c[{K, K+1}].scenery() = { scenery::generic, _control_panel, rotation::N, scenery::frame_t{0}, pass_mode::pass };
c.mark_modified();
}
diff --git a/scenery/scenery.json b/scenery/scenery.json
index 0d2495a9..e4599fca 100644
--- a/scenery/scenery.json
+++ b/scenery/scenery.json
@@ -7,7 +7,8 @@
{
"name": "control panel (wall) 1",
"type": "generic",
- "atlas-name": "control-panel"
+ "atlas-name": "control-panel",
+ "pass-mode": "pass"
},
{
"name": "bench1",
diff --git a/serialize/pass-mode.cpp b/serialize/pass-mode.cpp
new file mode 100644
index 00000000..6d52a5de
--- /dev/null
+++ b/serialize/pass-mode.cpp
@@ -0,0 +1,44 @@
+#include "pass-mode.hpp"
+#include "compat/exception.hpp"
+#include "serialize/corrade-string.hpp"
+#include <nlohmann/json.hpp>
+#include <Corrade/Containers/StringStlView.h>
+
+namespace nlohmann {
+
+using namespace floormat;
+
+static constexpr struct {
+ pass_mode mode;
+ StringView str;
+} table[] = {
+ { pass_mode::shoot_through, "shoot-through"_s },
+ { pass_mode::pass, "pass"_s },
+ { pass_mode::blocked, "blocked"_s },
+ { pass_mode::see_through, "see-through"_s },
+};
+
+void adl_serializer<pass_mode>::to_json(json& j, pass_mode val)
+{
+ for (const auto [mode, str] : table)
+ if (mode == val)
+ {
+ j = str;
+ return;
+ }
+ fm_throw("invalid pass mode '{}'"_cf, std::size_t(val));
+}
+
+void adl_serializer<pass_mode>::from_json(const json& j, pass_mode& val)
+{
+ StringView value = j;
+ for (const auto [mode, str] : table)
+ if (str == value)
+ {
+ val = mode;
+ return;
+ }
+ fm_throw("invalid pass mode '{}'"_cf, value);
+}
+
+} // namespace nlohmann
diff --git a/serialize/pass-mode.hpp b/serialize/pass-mode.hpp
new file mode 100644
index 00000000..a3e1cd66
--- /dev/null
+++ b/serialize/pass-mode.hpp
@@ -0,0 +1,13 @@
+#pragma once
+#include "src/pass-mode.hpp"
+#include <nlohmann/json_fwd.hpp>
+
+namespace nlohmann {
+
+template<>
+struct adl_serializer<floormat::pass_mode> {
+ static void to_json(json& j, floormat::pass_mode val);
+ static void from_json(const json& j, floormat::pass_mode& val);
+};
+
+} // namespace nlohmann
diff --git a/serialize/scenery.cpp b/serialize/scenery.cpp
index 7b402945..ccc80270 100644
--- a/serialize/scenery.cpp
+++ b/serialize/scenery.cpp
@@ -4,6 +4,7 @@
#include "loader/loader.hpp"
#include "serialize/corrade-string.hpp"
#include "loader/scenery.hpp"
+#include "serialize/pass-mode.hpp"
#include <Corrade/Containers/StringStlView.h>
#include <nlohmann/json.hpp>
@@ -85,8 +86,7 @@ void adl_serializer<scenery_proto>::to_json(json& j, const scenery_proto& val)
j["atlas-name"] = val.atlas->name();
j["frame"] = f.frame;
j["rotation"] = f.r;
- j["passable"] = f.passable;
- j["blocks-view"] = f.blocks_view;
+ j["pass-mode"] = f.passability;
j["active"] = f.active;
j["interactive"] = f.interactive;
}
@@ -108,17 +108,16 @@ void adl_serializer<scenery_proto>::from_json(const json& j, scenery_proto& val)
auto type = scenery_type::generic; get("type", type);
auto r = val.atlas->first_rotation(); get("rotation", r);
- auto frame = f.frame; get("frame", frame);
- bool passable = f.passable; get("passable", passable);
- bool blocks_view = f.blocks_view; get("blocks-view", blocks_view);
- bool active = f.active; get("active", active);
+ auto frame = f.frame; get("frame", frame);
+ pass_mode pass = f.passability; get("pass-mode", pass);
+ bool active = f.active; get("active", active);
switch (type)
{
default:
fm_abort("unhandled scenery type '%u'", (unsigned)type);
case scenery_type::generic:
- f = { scenery::generic, *val.atlas, r, frame, passable, blocks_view, active };
+ f = { scenery::generic, *val.atlas, r, frame, pass, active };
break;
case scenery_type::door:
f = { scenery::door, *val.atlas, r, false };
diff --git a/serialize/world-impl.hpp b/serialize/world-impl.hpp
index ea2a9cde..99db4cc0 100644
--- a/serialize/world-impl.hpp
+++ b/serialize/world-impl.hpp
@@ -38,7 +38,8 @@ constexpr inline proto_t min_proto_version = 1;
constexpr inline auto chunk_magic = (std::uint16_t)~0xc0d3;
constexpr inline auto scenery_magic = (std::uint16_t)~0xb00b;
-constexpr inline std::underlying_type_t<pass_mode> pass_mask = pass_blocked | pass_shoot_through | pass_ok;
+using pass_mode_ = std::underlying_type_t<pass_mode>;
+constexpr inline pass_mode_ pass_mask = pass_mode_COUNT - 1;
constexpr inline auto pass_bits = std::bit_width(pass_mask);
template<typename T> constexpr inline auto highbit = T(1) << sizeof(T)*8-1;
diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp
index b6cf8839..b0e14254 100644
--- a/serialize/world-reader.cpp
+++ b/serialize/world-reader.cpp
@@ -53,8 +53,7 @@ template<typename T>
bool read_scenery_flags(binary_reader<T>& s, scenery& sc)
{
std::uint8_t flags; flags << s;
- sc.passable = !!(flags & 1 << 0);
- sc.blocks_view = !!(flags & 1 << 1);
+ sc.passability = pass_mode(flags & pass_mask);
sc.active = !!(flags & 1 << 2);
sc.closing = !!(flags & 1 << 3);
sc.interactive = !!(flags & 1 << 4);
@@ -148,7 +147,7 @@ void reader_state::read_chunks(reader_t& s)
return { atlas, v };
};
- t.pass_mode() = pass_mode(flags & pass_mask);
+ t.passability() = pass_mode(flags & pass_mask);
if (flags & meta_ground)
t.ground() = make_atlas();
if (flags & meta_wall_n)
@@ -179,13 +178,13 @@ void reader_state::read_chunks(reader_t& s)
switch (auto x = pass_mode(flags & pass_mask))
{
- case pass_shoot_through:
- case pass_blocked:
- case pass_ok:
- t.pass_mode() = x;
+ case pass_mode::shoot_through:
+ case pass_mode::blocked:
+ case pass_mode::pass:
+ t.passability() = x;
break;
default: [[unlikely]]
- fm_throw("bad pass mode '{}' for tile {}"_cf, i, x);
+ fm_throw("bad pass mode '{}' for tile {}"_cf, i, pass_mode_(x));
}
}
}
diff --git a/serialize/world-writer.cpp b/serialize/world-writer.cpp
index 7cd4b6d9..5ff0a39c 100644
--- a/serialize/world-writer.cpp
+++ b/serialize/world-writer.cpp
@@ -180,8 +180,7 @@ template<typename T>
void write_scenery_flags(binary_writer<T>& s, const scenery& proto)
{
std::uint8_t flags = 0;
- flags |= (1 << 0) * proto.passable;
- flags |= (1 << 1) * proto.blocks_view;
+ flags |= pass_mode_(proto.passability) & pass_mask;
flags |= (1 << 2) * proto.active;
flags |= (1 << 3) * proto.closing;
flags |= (1 << 4) * proto.interactive;
@@ -320,8 +319,8 @@ void writer_state::serialize_chunk(const chunk& c, chunk_coords coord)
if (flags != 0 && ashortp(img_g) && ashortp(img_n) && ashortp(img_w))
flags |= meta_short_atlasid;
- fm_debug_assert((x.pass_mode & pass_mask) == x.pass_mode);
- flags |= x.pass_mode;
+ fm_debug_assert((pass_mode_(x.passability) & pass_mask) == pass_mode_(x.passability));
+ flags |= pass_mode_(x.passability);
s << flags;
diff --git a/src/pass-mode.hpp b/src/pass-mode.hpp
new file mode 100644
index 00000000..a60a8188
--- /dev/null
+++ b/src/pass-mode.hpp
@@ -0,0 +1,10 @@
+#pragma once
+#include <cstdint>
+
+namespace floormat {
+
+enum class pass_mode : std::uint8_t { shoot_through, pass, blocked, see_through };
+constexpr inline std::uint8_t pass_mode_COUNT = std::uint8_t(pass_mode::see_through) + 1;
+static_assert(pass_mode_COUNT == 4);
+
+} // namespace floormat
diff --git a/src/scenery.cpp b/src/scenery.cpp
index 4056f49f..28884ad8 100644
--- a/src/scenery.cpp
+++ b/src/scenery.cpp
@@ -29,11 +29,11 @@ scenery_ref::operator scenery_proto() const noexcept { return { atlas, frame };
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(none_tag_t) noexcept {}
scenery::scenery(generic_tag_t, const anim_atlas& atlas, rotation r, frame_t frame,
- bool passable, bool blocks_view, bool active, bool interactive) :
+ pass_mode pass, bool active, bool interactive) :
frame{frame}, r{r}, type{scenery_type::generic},
- passable{passable}, blocks_view{blocks_view}, active{active},
+ passability{pass}, active{active},
interactive{interactive}
{
fm_assert(r < rotation_COUNT);
@@ -43,7 +43,8 @@ scenery::scenery(generic_tag_t, const anim_atlas& atlas, rotation r, frame_t fra
scenery::scenery(door_tag_t, const anim_atlas& atlas, rotation r, bool is_open) :
frame{frame_t(is_open ? 0 : atlas.group(r).frames.size()-1)},
r{r}, type{scenery_type::door},
- passable{is_open}, blocks_view{!is_open}, interactive{true}
+ passability{is_open ? pass_mode::pass : pass_mode::blocked},
+ interactive{true}
{
fm_assert(r < rotation_COUNT);
fm_assert(atlas.group(r).frames.size() >= 2);
@@ -78,8 +79,12 @@ void scenery::update(float dt, const anim_atlas& anim)
const std::int8_t dir = closing ? 1 : -1;
const int fr = frame + dir*n;
active = fr > 0 && fr < nframes-1;
- passable = fr <= 0;
- blocks_view = !passable;
+ if (fr <= 0)
+ passability = pass_mode::pass;
+ else if (fr >= nframes-1)
+ passability = pass_mode::blocked;
+ else
+ passability = pass_mode::see_through;
frame = (frame_t)std::clamp(fr, 0, nframes-1);
if (!active)
delta = closing = 0;
diff --git a/src/scenery.hpp b/src/scenery.hpp
index 4ed55d20..b94e1d2a 100644
--- a/src/scenery.hpp
+++ b/src/scenery.hpp
@@ -1,4 +1,5 @@
#pragma once
+#include "pass-mode.hpp"
#include <cstdint>
#include <memory>
#include <type_traits>
@@ -35,8 +36,7 @@ struct scenery final
frame_t frame = 0;
rotation r : 3 = rotation::N;
scenery_type type : 3 = scenery_type::none;
- std::uint8_t passable : 1 = false;
- std::uint8_t blocks_view : 1 = false; // todo
+ pass_mode passability : 2 = pass_mode{0};
std::uint8_t active : 1 = false;
std::uint8_t closing : 1 = false;
std::uint8_t interactive : 1 = false;
@@ -44,7 +44,7 @@ struct scenery final
scenery() noexcept;
scenery(none_tag_t) noexcept;
scenery(generic_tag_t, const anim_atlas& atlas, rotation r, frame_t frame = 0,
- bool passable = false, bool blocks_view = false, bool active = false, bool interactive = false);
+ pass_mode passability = pass_mode::shoot_through, bool active = false, bool interactive = false);
scenery(door_tag_t, const anim_atlas& atlas, rotation r, bool is_open = false);
bool operator==(const scenery&) const noexcept;
diff --git a/src/tile.cpp b/src/tile.cpp
index b9ed5ab6..419e59a3 100644
--- a/src/tile.cpp
+++ b/src/tile.cpp
@@ -7,8 +7,9 @@ pass_mode_ref::pass_mode_ref(chunk& c, std::uint8_t i) noexcept : _chunk{&c}, i{
{
}
-pass_mode_ref& pass_mode_ref::operator=(pass_mode x) noexcept
+pass_mode_ref& pass_mode_ref::operator=(pass_mode val) noexcept
{
+ auto x = std::underlying_type_t<pass_mode>(val) & pass_mode_COUNT;
auto& bitset = _chunk->_passability;
bitset[i*2 + 0] = x & 1;
bitset[i*2 + 1] = x >> 1 & 1;
@@ -63,15 +64,15 @@ tile_image_proto tile_ref::wall_north() const noexcept { return { _chunk->_wall_
tile_image_proto tile_ref::wall_west() const noexcept { return { _chunk->_wall_atlases[i*2+1], _chunk->_wall_variants[i*2+1] }; }
scenery_proto tile_ref::scenery() const noexcept { return { _chunk->_scenery_atlases[i], _chunk->_scenery_variants[i] }; }
-pass_mode_ref tile_ref::pass_mode() noexcept { return { *_chunk, i }; }
-pass_mode tile_ref::pass_mode() const noexcept { return pass_mode_ref { *const_cast<struct chunk*>(_chunk), i }; }
+pass_mode_ref tile_ref::passability() noexcept { return { *_chunk, i }; }
+pass_mode tile_ref::passability() const noexcept { return pass_mode_ref { *const_cast<struct chunk*>(_chunk), i }; }
tile_ref::operator tile_proto() const noexcept
{
return {
_chunk->_ground_atlases[i], _chunk->_wall_atlases[i*2+0], _chunk->_wall_atlases[i*2+1], _chunk->_scenery_atlases[i],
_chunk->_ground_variants[i], _chunk->_wall_variants[i*2+0], _chunk->_wall_variants[i*2+1], _chunk->_scenery_variants[i],
- pass_mode(),
+ passability(),
};
}
@@ -84,7 +85,7 @@ bool operator==(const tile_ref& a, const tile_ref& b) noexcept
a.wall_north() == b.wall_north() &&
a.wall_west() == b.wall_west() &&
a.scenery() == b.scenery() &&
- a.pass_mode() == b.pass_mode();
+ a.passability() == b.passability();
}
} // namespace floormat
diff --git a/src/tile.hpp b/src/tile.hpp
index 387f7ff0..543b70b6 100644
--- a/src/tile.hpp
+++ b/src/tile.hpp
@@ -1,15 +1,13 @@
#pragma once
#include "tile-image.hpp"
#include "scenery.hpp"
+#include "pass-mode.hpp"
namespace floormat {
struct chunk;
struct anim_atlas;
-// zero is the default, see bitset in chunk.hpp
-enum pass_mode : unsigned char { pass_shoot_through, pass_ok, pass_blocked, };
-
struct pass_mode_ref final
{
pass_mode_ref(chunk& c, std::uint8_t i) noexcept;
@@ -28,7 +26,7 @@ struct tile_proto final
std::shared_ptr<anim_atlas> scenery_atlas;
variant_t ground_variant = 0, wall_north_variant = 0, wall_west_variant = 0;
struct scenery scenery_frame;
- enum pass_mode pass_mode = pass_mode::pass_shoot_through;
+ pass_mode passability = pass_mode{0};
tile_image_proto ground() const noexcept;
tile_image_proto wall_north() const noexcept;
@@ -62,8 +60,8 @@ struct tile_ref final
std::shared_ptr<const tile_atlas> wall_west_atlas() const noexcept;
std::shared_ptr<const anim_atlas> scenery_atlas() const noexcept;
- pass_mode_ref pass_mode() noexcept;
- enum pass_mode pass_mode() const noexcept;
+ pass_mode_ref passability() noexcept;
+ pass_mode passability() const noexcept;
explicit operator tile_proto() const noexcept;