diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-01-23 15:11:26 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-01-23 15:11:26 +0100 |
commit | c554cdbc0cf894ccc6c330e0743649a4bdb34658 (patch) | |
tree | 80b5fa2e64136eb2740d9c9524daf92b8a447b3d /serialize | |
parent | 573f8f2bcbfd86119e00a13fedc5abf2bf7deafb (diff) |
a
Diffstat (limited to 'serialize')
-rw-r--r-- | serialize/old-savegame.cpp | 49 | ||||
-rw-r--r-- | serialize/savegame.cpp | 67 | ||||
-rw-r--r-- | serialize/scenery.cpp | 51 |
3 files changed, 123 insertions, 44 deletions
diff --git a/serialize/old-savegame.cpp b/serialize/old-savegame.cpp index d63447a4..8a050022 100644 --- a/serialize/old-savegame.cpp +++ b/serialize/old-savegame.cpp @@ -171,9 +171,17 @@ bool read_object_flags(binary_reader<T>& s, U& e) fm_throw("invalid object type '{}'"_cf, (int)e.type); if constexpr(tag == object_type::scenery) { - e.active = !!(flags & 1 << 2); - e.closing = !!(flags & 1 << 3); - e.interactive = !!(flags & 1 << 4); + if (auto* val = std::get_if<generic_scenery_proto>(&e.subtype)) + { + val->active = !!(flags & 1 << 2); + val->interactive = !!(flags & 1 << 4); + } + else if (auto* val = std::get_if<door_scenery_proto>(&e.subtype)) + { + val->active = !!(flags & 1 << 2); + val->closing = !!(flags & 1 << 3); + val->interactive = !!(flags & 1 << 4); + } } else if constexpr(tag == object_type::critter) { @@ -461,8 +469,16 @@ void reader_state::read_chunks(reader_t& s) s >> sc.offset[1]; } read_bbox(s, sc); - if (sc.active) - sc.delta << s; + if (const auto* val = std::get_if<generic_scenery_proto>(&sc.subtype)) + { + if (val->active) + sc.delta << s; + } + else if (const auto* val = std::get_if<door_scenery_proto>(&sc.subtype)) + { + if (val->active) + sc.delta << s; + } } auto e = _world->make_object<scenery, false>(oid, {ch, local}, sc); (void)e; @@ -561,12 +577,25 @@ void reader_state::read_old_scenery(reader_t& s, chunk_coords_ ch, size_t i) sc.bbox_offset[0] << s; sc.bbox_offset[1] << s; } - if (sc.active) + if (auto* val = std::get_if<generic_scenery_proto>(&sc.subtype)) { - if (PROTO >= 4) [[likely]] - sc.delta << s; - else - sc.delta = (uint16_t)Math::clamp(int(s.read<float>() * 65535), 0, 65535); + if (val->active) + { + if (PROTO >= 4) [[likely]] + sc.delta << s; + else + sc.delta = (uint16_t)Math::clamp(int(s.read<float>() * 65535), 0, 65535); + } + } + else if (auto* val = std::get_if<door_scenery_proto>(&sc.subtype)) + { + if (val->active) + { + if (PROTO >= 4) [[likely]] + sc.delta << s; + else + sc.delta = (uint16_t)Math::clamp(int(s.read<float>() * 65535), 0, 65535); + } } } global_coords coord{ch, local_coords{i}}; diff --git a/serialize/savegame.cpp b/serialize/savegame.cpp index e7d24195..a71118e8 100644 --- a/serialize/savegame.cpp +++ b/serialize/savegame.cpp @@ -148,7 +148,6 @@ struct visitor_ break; case object_type::scenery: case object_type::critter: - case object_type::door_new: static_cast<Derived&>(*this).visit(non_const(obj.atlas), atlas_type::anim, f); break; case object_type::none: @@ -172,11 +171,9 @@ struct visitor_ switch (type) { - case object_type::door_new: fm_assert(false && "todo"); case object_type::critter: do_visit(static_cast<critter&>(obj), f); return; case object_type::scenery: do_visit(static_cast<scenery&>(obj), f); return; case object_type::light: do_visit(static_cast<light&>(obj), f); return; - //case object_type::door: do_visit(static_cast<door&>(obj), f); return; case object_type::COUNT: case object_type::none: break; @@ -224,37 +221,71 @@ struct visitor_ setter(obj, flags & bits); } - template<typename F> void visit(scenery& obj, F&& f) + template<typename F> void visit(generic_scenery& s, F&& f) { - auto sc_type = obj.sc_type; - do_visit(sc_type, f); - obj.sc_type = sc_type; + constexpr struct { + uint8_t bits; + bool(*getter)(const generic_scenery&); + void(*setter)(generic_scenery&, bool); + } pairs[] = { + { 1 << 0, + [](const auto& sc) { return !!sc.active; }, + [](auto& sc, bool value) { sc.active = value; } + }, + { 1 << 2, + [](const auto& sc) { return !!sc.interactive; }, + [](auto& sc, bool value) { sc.interactive = value; } + }, + }; + uint8_t flags = 0; + for (auto [bits, getter, setter] : pairs) + flags |= bits * getter(s); + do_visit(flags, f); + for (auto [bits, getter, setter] : pairs) + setter(s, flags & bits); + } + + template<typename F> void visit(door_scenery& s, F&& f) + { constexpr struct { uint8_t bits; - bool(*getter)(const scenery&); - void(*setter)(scenery&, bool); + bool(*getter)(const door_scenery&); + void(*setter)(door_scenery&, bool); } pairs[] = { { 1 << 0, - [](const scenery& sc) { return !!sc.active; }, - [](scenery& sc, bool value) { sc.active = value; } + [](const auto& sc) { return !!sc.active; }, + [](auto& sc, bool value) { sc.active = value; } }, { 1 << 1, - [](const scenery& sc) { return !!sc.closing; }, - [](scenery& sc, bool value) { sc.closing = value; } + [](const auto& sc) { return !!sc.closing; }, + [](auto& sc, bool value) { sc.closing = value; } }, { 1 << 2, - [](const scenery& sc) { return !!sc.interactive; }, - [](scenery& sc, bool value) { sc.interactive = value; } + [](const auto& sc) { return !!sc.interactive; }, + [](auto& sc, bool value) { sc.interactive = value; } }, }; uint8_t flags = 0; for (auto [bits, getter, setter] : pairs) - flags |= bits * getter(obj); + flags |= bits * getter(s); do_visit(flags, f); for (auto [bits, getter, setter] : pairs) - setter(obj, flags & bits); + setter(s, flags & bits); + } + + template<typename F> void visit(scenery& obj, F&& f) + { + auto sc_type = obj.scenery_type(); + do_visit(sc_type, f); + if (sc_type != obj.scenery_type()) + obj.subtype = scenery::subtype_from_scenery_type(obj.id, *obj.c, sc_type); + + std::visit( + [&]<typename T>(T& x) { return do_visit(x, f); }, + obj.subtype + ); } template<typename F> void visit(light& obj, F&& f) @@ -738,8 +769,6 @@ struct reader final : visitor_<reader> case object_type::none: case object_type::COUNT: break; - case object_type::door_new: - fm_assert(false && "todo"); case object_type::light: obj = w.make_unconnected_object<light>(); goto ok; case object_type::critter: diff --git a/serialize/scenery.cpp b/serialize/scenery.cpp index 41b99218..158b4773 100644 --- a/serialize/scenery.cpp +++ b/serialize/scenery.cpp @@ -84,6 +84,8 @@ void adl_serializer<scenery_proto>::to_json(json& j, const scenery_proto& f) { fm_assert(f.atlas); const scenery_proto default_scenery; + const generic_scenery_proto default_generic_scenery; + const door_scenery_proto default_door_scenery; if (f.type != default_scenery.type) j["type"] = f.type; j["atlas-name"] = f.atlas->name(); @@ -93,10 +95,22 @@ void adl_serializer<scenery_proto>::to_json(json& j, const scenery_proto& f) j["rotation"] = f.r; if (f.pass != default_scenery.pass) j["pass-mode"] = f.pass; - if (f.active != default_scenery.active) - j["active"] = f.active; - if (f.interactive != default_scenery.interactive) - j["interactive"] = f.interactive; + std::visit(overloaded { + [&](const generic_scenery_proto& x) { + if (x.active != default_generic_scenery.active) + j["active"] = x.active; + if (x.interactive != default_generic_scenery.interactive) + j["interactive"] = x.interactive; + }, + [&](const door_scenery_proto& x) { + if (x.active != default_door_scenery.active) + j["active"] = x.active; + if (x.interactive != default_door_scenery.interactive) + j["interactive"] = x.interactive; + if (x.closing != default_door_scenery.closing) + j["closing"] = x.closing; + }, + }, f.subtype); if (f.offset != default_scenery.offset) j["offset"] = Vector2i(f.offset); if (f.bbox_offset != default_scenery.bbox_offset) @@ -114,17 +128,19 @@ void adl_serializer<scenery_proto>::from_json(const json& j, scenery_proto& f) value = j[s]; }; + const generic_scenery_proto G; + const door_scenery_proto D; + StringView atlas_name = j["atlas-name"]; fm_soft_assert(!atlas_name.isEmpty()); f = {}; f.atlas = loader.anim_atlas(atlas_name, loader_::SCENERY_PATH); - auto type = scenery_type::generic; get("type", type); auto frame = f.frame; get("frame", frame); auto r = f.atlas->first_rotation(); get("rotation", r); pass_mode pass = f.pass; get("pass-mode", pass); - bool active = f.active; get("active", active); - bool interactive = f.interactive; get("interactive", interactive); + bool active = G.active; get("active", active); + bool interactive = G.interactive; get("interactive", interactive); auto offset = Vector2i(f.offset); get("offset", offset); auto bbox_offset = Vector2i(f.bbox_offset); get("bbox-offset", bbox_offset); auto bbox_size = Vector2ui(f.bbox_size); get("bbox-size", bbox_size); @@ -136,32 +152,37 @@ void adl_serializer<scenery_proto>::from_json(const json& j, scenery_proto& f) { default: fm_throw("unhandled scenery type '{}'"_cf, (unsigned)type); - case scenery_type::generic: + case scenery_type::generic: { + auto s = generic_scenery_proto{}; f.type = object_type::scenery; - f.sc_type = scenery_type::generic; f.r = r; f.frame = frame; f.pass = pass; - f.active = active; - f.interactive = interactive; + s.active = active; + s.interactive = interactive; f.offset = Vector2b(offset); f.bbox_offset = Vector2b(bbox_offset); f.bbox_size = Vector2ub(bbox_size); + f.subtype = s; break; - case scenery_type::door: + } + case scenery_type::door: { fm_assert(f.atlas->info().fps > 0 && f.atlas->info().nframes > 0); + auto s = door_scenery_proto{}; f.type = object_type::scenery; - f.sc_type = scenery_type::door; f.r = r; f.frame = uint16_t(f.atlas->group(r).frames.size()-1); f.pass = pass_mode::blocked; - f.interactive = true; - f.closing = false; + s.active = false; + s.interactive = true; + s.closing = false; f.offset = Vector2b(offset); f.bbox_offset = Vector2b(bbox_offset); f.bbox_size = Vector2ub(bbox_size); + f.subtype = s; break; } + } } void adl_serializer<serialized_scenery>::to_json(json& j, const serialized_scenery& val) |