summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--loader/loader.cpp1
-rw-r--r--loader/loader.hpp1
-rw-r--r--serialize/wall-atlas.cpp95
-rw-r--r--serialize/wall-atlas.hpp10
-rw-r--r--src/wall-atlas.cpp18
-rw-r--r--src/wall-atlas.hpp4
6 files changed, 116 insertions, 13 deletions
diff --git a/loader/loader.cpp b/loader/loader.cpp
index 19e07bc4..7d95da0e 100644
--- a/loader/loader.cpp
+++ b/loader/loader.cpp
@@ -40,5 +40,6 @@ const StringView loader_::ANIM_PATH = "anim/"_s;
const StringView loader_::SCENERY_PATH = "scenery/"_s;
const StringView loader_::TEMP_PATH = "../../../"_s;
const StringView loader_::VOBJ_PATH = "vobj/"_s;
+const StringView loader_::WALL_TILESET_PATH = "wall-tilesets/"_s;
} // namespace floormat
diff --git a/loader/loader.hpp b/loader/loader.hpp
index f94b530e..19d93021 100644
--- a/loader/loader.hpp
+++ b/loader/loader.hpp
@@ -52,6 +52,7 @@ struct loader_
static const StringView SCENERY_PATH;
static const StringView TEMP_PATH;
static const StringView VOBJ_PATH;
+ static const StringView WALL_TILESET_PATH;
protected:
loader_();
diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp
index 5db79e05..3749be64 100644
--- a/serialize/wall-atlas.cpp
+++ b/serialize/wall-atlas.cpp
@@ -1,11 +1,16 @@
#include "wall-atlas.hpp"
#include "magnum-vector2i.hpp"
#include "magnum-vector.hpp"
+#include "corrade-string.hpp"
#include "compat/exception.hpp"
+#include "loader/loader.hpp"
#include <utility>
#include <string_view>
+#include <Corrade/Containers/PairStl.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Containers/StringStlView.h>
+#include <Magnum/ImageView.h>
+#include <Magnum/Trade/ImageData.h>
#include <nlohmann/json.hpp>
// todo add test on dummy files that generates 100% coverage on the j.contains() blocks!
@@ -31,6 +36,27 @@ StringView direction_index_to_name(size_t i)
return wall_atlas::directions[i].name;
}
+Array<Frame> read_all_frames(const json& jroot)
+{
+ fm_assert(jroot.contains("frames"sv));
+
+ Array<Frame> frames;
+ const auto& jframes = jroot["frames"sv];
+
+ fm_assert(jframes.is_array());
+ const auto sz = jframes.size();
+ frames = Array<Frame>{sz};
+
+ for (auto i = 0uz; i < sz; i++)
+ {
+ const auto& jframe = jframes[i];
+ fm_assert(jframe.is_object());
+ frames[i] = jframe;
+ }
+
+ return frames;
+}
+
Group read_group_metadata(const json& jgroup)
{
fm_assert(jgroup.is_object());
@@ -40,11 +66,10 @@ Group read_group_metadata(const json& jgroup)
{
int count = 0, index = -1;
bool has_count = jgroup.contains("count"sv) && (count = jgroup["count"sv]) != 0,
- has_index = jgroup.contains("offset"sv);
- if (has_index)
- index = jgroup["offset"sv];
+ has_index = jgroup.contains("offset"sv) && (index = jgroup["offset"sv]) != -1;
fm_soft_assert(has_count == has_index);
fm_soft_assert(!has_index || index >= 0 && index < 1 << 20);
+ fm_soft_assert(count >= 0);
// todo check index within range
}
@@ -86,6 +111,23 @@ Direction read_direction_metadata(const json& jroot, Direction_ dir)
return val;
}
+Pair<Array<Direction>, std::array<DirArrayIndex, 4>> read_all_directions(const json& jroot)
+{
+ size_t count = 0;
+ for (auto [str, _] : wall_atlas::directions)
+ if (jroot.contains(str))
+ count++;
+ Array<Direction> array{count};
+ std::array<DirArrayIndex, 4> map = {};
+ for (uint8_t i = 0; auto [str, dir] : wall_atlas::directions)
+ if (jroot.contains(str))
+ {
+ map[(size_t)dir] = {.val = i};
+ array[i++] = read_direction_metadata(jroot, dir);
+ }
+ return { std::move(array), std::move(map) };
+}
+
Info read_info_header(const json& jroot)
{
fm_soft_assert(jroot.contains(("name"sv)));
@@ -97,12 +139,26 @@ Info read_info_header(const json& jroot)
return val;
}
+void write_all_frames(json& jroot, ArrayView<const Frame> array)
+{
+ auto jframes = json{json::value_t::array};
+ for (const Frame& frame : array)
+ {
+ json jframe = frame;
+ jframes.push_back(std::move(jframe));
+ }
+ jroot["frames"sv] = std::move(jframes);
+}
+
void write_group_metadata(json& jgroup, const Group& val)
{
fm_assert(jgroup.is_object());
- fm_assert(jgroup.empty());
- jgroup["offset"sv] = val.index;
+ if (val.index != (uint32_t)-1)
+ jgroup["offset"sv] = val.index;
+ else
+ jgroup["offset"sv] = -1;
+
jgroup["count"sv] = val.count;
jgroup["pixel-size"sv] = val.pixel_size;
jgroup["tint-mult"sv] = Vector4(val.tint_mult);
@@ -114,8 +170,6 @@ void write_group_metadata(json& jgroup, const Group& val)
void write_direction_metadata(json& jdir, const Direction& dir)
{
- //auto name = std::string_view{direction_index_to_name((size_t)i)};
-
for (auto [s_, memfn, tag] : Direction::members)
{
std::string_view s = s_;
@@ -138,14 +192,13 @@ void write_all_directions(json& jroot, const wall_atlas& a)
{
auto jdir = json{json::value_t::object};
write_direction_metadata(jdir, *dir);
- jroot[name] = jdir;
+ jroot[name] = std::move(jdir);
}
}
}
void write_info_header(json& jroot, const Info& info)
-{
- jroot["name"sv] = info.name;
+{ jroot["name"sv] = info.name;
if (info.description)
jroot["description"sv] = info.description;
jroot["depth"sv] = info.depth;
@@ -153,21 +206,41 @@ void write_info_header(json& jroot, const Info& info)
} // namespace floormat::Wall::detail
+namespace floormat::Wall {
+
+NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Frame, offset)
+NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Info, name, description, depth)
+
+} // namespace floormat::Wall
+
namespace nlohmann {
using namespace floormat;
+using namespace floormat::Wall;
using namespace floormat::Wall::detail;
+void adl_serializer<Frame>::to_json(nlohmann::json& j, const Frame& x) { using nlohmann::to_json; to_json(j, x); }
+void adl_serializer<Frame>::from_json(const json& j, Frame& x) { using nlohmann::from_json; from_json(j, x); }
+
void adl_serializer<std::shared_ptr<wall_atlas>>::to_json(json& j, const std::shared_ptr<const wall_atlas>& x)
{
fm_assert(x != nullptr);
write_info_header(j, x->info());
write_all_directions(j, *x);
+ write_all_frames(j, x->raw_frame_array());
}
void adl_serializer<std::shared_ptr<wall_atlas>>::from_json(const json& j, std::shared_ptr<wall_atlas>& x)
{
-
+ auto info = read_info_header(j);
+ fm_assert(loader.check_atlas_name(info.name));
+ auto [dirs, map] = read_all_directions(j);
+ Array<Frame> frames;
+ auto img = loader.texture(loader.WALL_TILESET_PATH, info.name);
+ if (j.contains("frames"sv))
+ frames = read_all_frames(j);
+
+ x = std::make_shared<wall_atlas>(std::move(info), img, std::move(frames), std::move(dirs), map);
}
} // namespace nlohmann
diff --git a/serialize/wall-atlas.hpp b/serialize/wall-atlas.hpp
index edb8b29b..7f578a5d 100644
--- a/serialize/wall-atlas.hpp
+++ b/serialize/wall-atlas.hpp
@@ -6,6 +6,13 @@
namespace nlohmann {
template<>
+struct adl_serializer<floormat::Wall::Frame>
+{
+ static void to_json(json& j, const floormat::Wall::Frame& x);
+ static void from_json(const json& j, floormat::Wall::Frame& x);
+};
+
+template<>
struct adl_serializer<std::shared_ptr<floormat::wall_atlas>>
{
static void to_json(json& j, const std::shared_ptr<const floormat::wall_atlas>& x);
@@ -21,10 +28,13 @@ using nlohmann::json;
uint8_t direction_index_from_name(StringView s);
StringView direction_index_to_name(size_t i);
+[[nodiscard]] Array<Frame> read_all_frames(const json& jroot);
[[nodiscard]] Group read_group_metadata(const json& jgroup);
[[nodiscard]] Direction read_direction_metadata(const json& jroot, Direction_ dir);
+Pair<Array<Direction>, std::array<DirArrayIndex, 4>> read_all_directions(const json& jroot);
Info read_info_header(const json& jroot);
+void write_all_frames(json& jframes, ArrayView<const Frame> array);
void write_group_metadata(json& jgroup, const Group& val);
void write_direction_metadata(json& jdir, const Direction& dir);
void write_all_directions(json& jroot, const wall_atlas& a);
diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp
index 96758983..402d5d66 100644
--- a/src/wall-atlas.cpp
+++ b/src/wall-atlas.cpp
@@ -21,6 +21,23 @@ wall_atlas::wall_atlas(Info info, const ImageView2D& image,
_info{ std::move(info) },
_direction_to_Direction_array_index{ direction_to_DirArrayIndex }
{
+ const auto frame_count = frames.size();
+ for (const Direction& dir : directions)
+ {
+ for (auto [_str, _group, tag] : Direction::members)
+ {
+ const auto* g = group(dir, tag);
+ if (!g)
+ continue;
+ fm_assert(g->count > 0 == g->index < (uint32_t)-1);
+ if (g->count > 0)
+ {
+ fm_assert(g->index < frame_count);
+ fm_assert(g->index + g->count <= frame_count);
+ }
+ }
+ }
+
_texture.setLabel(_info.name)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
@@ -91,6 +108,7 @@ auto wall_atlas::direction(size_t dir) const -> const Direction*
uint8_t wall_atlas::direction_count() const { return (uint8_t)_dir_array.size(); }
auto wall_atlas::raw_frame_array() const -> ArrayView<const Frame> { return _frame_array; }
auto wall_atlas::info() const -> const Info& { return _info; }
+GL::Texture2D& wall_atlas::texture() { fm_debug_assert(_texture.id()); return _texture; }
StringView wall_atlas::name() const { return _info.name; }
size_t wall_atlas::enum_to_index(enum rotation r)
diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp
index 3d97c0e7..65b15183 100644
--- a/src/wall-atlas.hpp
+++ b/src/wall-atlas.hpp
@@ -95,7 +95,7 @@ class wall_atlas final
Array<Direction> _dir_array;
Array<Frame> _frame_array;
Info _info;
- GL::Texture2D _texture;
+ GL::Texture2D _texture{NoCreate};
std::array<DirArrayIndex, 4> _direction_to_Direction_array_index;
Direction* get_Direction(Direction_ num) const;
@@ -104,7 +104,6 @@ public:
fm_DECLARE_DELETED_MOVE_ASSIGNMENT(wall_atlas);
wall_atlas() noexcept;
~wall_atlas() noexcept;
-
wall_atlas(Info info, const ImageView2D& image,
Array<Frame> frames, Array<Direction> directions,
std::array<DirArrayIndex, 4> direction_to_DirArrayIndex);
@@ -118,6 +117,7 @@ public:
ArrayView<const Frame> frames(const Group& a) const;
ArrayView<const Frame> raw_frame_array() const;
const Info& info() const;
+ GL::Texture2D& texture();
static size_t enum_to_index(enum rotation x);