diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-12-02 14:44:32 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-12-02 14:46:59 +0100 |
commit | 889d2c0c0933cf2fd9e068b1d2b79eb936b29b58 (patch) | |
tree | cfc5f5b6e417c28482734645a69e0d49388fa5b3 | |
parent | 8dbf450e34121358992e48212ae22cb7f5fc92f9 (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.cpp | 2 | ||||
-rw-r--r-- | scenery/scenery.json | 3 | ||||
-rw-r--r-- | serialize/pass-mode.cpp | 44 | ||||
-rw-r--r-- | serialize/pass-mode.hpp | 13 | ||||
-rw-r--r-- | serialize/scenery.cpp | 13 | ||||
-rw-r--r-- | serialize/world-impl.hpp | 3 | ||||
-rw-r--r-- | serialize/world-reader.cpp | 15 | ||||
-rw-r--r-- | serialize/world-writer.cpp | 7 | ||||
-rw-r--r-- | src/pass-mode.hpp | 10 | ||||
-rw-r--r-- | src/scenery.cpp | 17 | ||||
-rw-r--r-- | src/scenery.hpp | 6 | ||||
-rw-r--r-- | src/tile.cpp | 11 | ||||
-rw-r--r-- | src/tile.hpp | 10 |
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; |