summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-11-05 07:39:06 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-11-05 07:39:06 +0100
commit98da53beb78d9a617a1c66b404e9a7d8469a443a (patch)
treee708c5133ea5705d402b31b16aadcb24ec25b6c1
parent8cd318bc55e9d1588307999618a0d8bef09f9f68 (diff)
a
-rw-r--r--serialize/wall-atlas.cpp69
-rw-r--r--serialize/wall-atlas.hpp6
-rw-r--r--src/wall-atlas.cpp50
-rw-r--r--src/wall-atlas.hpp40
-rw-r--r--test/CMakeLists.txt6
-rw-r--r--test/json/frameset-header.json9
-rw-r--r--test/wall-atlas.cpp38
-rw-r--r--wall-tileset-tool/main.cpp13
8 files changed, 185 insertions, 46 deletions
diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp
index d8fe8f60..23fbf1b3 100644
--- a/serialize/wall-atlas.cpp
+++ b/serialize/wall-atlas.cpp
@@ -3,6 +3,7 @@
#include "magnum-vector.hpp"
#include "compat/exception.hpp"
#include <utility>
+#include <string_view>
#include <Corrade/Containers/StringStl.h>
#include <nlohmann/json.hpp>
@@ -26,18 +27,22 @@ size_t rotation_from_name(StringView s)
fm_throw("bad rotation name '{}'"_cf, fmt::string_view{s.data(), s.size()});
}
-void read_frameset_metadata(const nlohmann::json& j, wall_frames& val)
+StringView rotation_to_name(size_t i)
{
+ fm_soft_assert(i < std::size(rotation_names));
+ return rotation_names[i];
+}
+
+void read_frameset_metadata(const nlohmann::json& j, wall_frames& val, size_t& rot)
+{
+ val = {};
+ rot = rotation_from_name(std::string{j["name"s]});
+
if (j.contains("pixel-size"s))
val.pixel_size = j["pixel-size"s];
if (j.contains("tint"s))
{
- auto& t = j["tint"s];
- fm_soft_assert(t.contains("mult"s) || t.contains("add"s));
- if (t.contains("mult"s))
- val.tint_mult = Vector4(t["mult"s]);
- if (t.contains("add"s))
- val.tint_add = Vector3(t["add"s]);
+ std::tie(val.tint_mult, val.tint_add) = std::pair<Vector4, Vector3>{j["tint"s]};
fm_soft_assert(val.tint_mult >= Color4{0});
}
if (j.contains("from-rotation"s))
@@ -48,17 +53,15 @@ void read_frameset_metadata(const nlohmann::json& j, wall_frames& val)
val.use_default_tint = j["use-default-tint"s];
}
-void write_frameset_metadata(nlohmann::json& j, const wall_atlas& a, const wall_frames& val)
+void write_frameset_metadata(nlohmann::json& j, const wall_atlas& a, const wall_frames& val, size_t rot)
{
constexpr wall_frames default_value;
-#if 0
- fm_soft_assert(val.index != default_value.index);
- fm_soft_assert(val.count != default_value.count);
- fm_soft_assert(val.pixel_size != default_value.pixel_size);
-#endif
-
- fm_soft_assert(val.index < a.array().size());
- fm_soft_assert(val.count != (uint32_t)-1 && val.count > 0);
+
+ fm_soft_assert(val.count != (uint32_t)-1);
+ fm_soft_assert(val.index == (uint32_t)-1 || val.index < a.frame_array().size());
+ fm_soft_assert((val.index == (uint32_t)-1) == (val.count == 0));
+
+ j["name"s] = rotation_to_name(rot);
j["pixel-size"s] = val.pixel_size;
if (val.tint_mult != default_value.tint_mult || val.tint_add != default_value.tint_add)
{
@@ -77,8 +80,42 @@ void write_frameset_metadata(nlohmann::json& j, const wall_atlas& a, const wall_
j["use-default-tint"s] = true;
}
+void read_framesets(const nlohmann::json& jf, wall_atlas_def& val)
+{
+ fm_soft_assert(jf.is_object());
+ fm_soft_assert(val.framesets == nullptr && val.frameset_count == 0);
+ uint8_t count = 0;
+
+ static_assert(std::size(rotation_names) == 4);
+ for (auto i = 0uz; i < 4; i++)
+ {
+ const auto& r = rotation_names[i];
+ auto key = std::string_view{r.data(), r.size()};
+ if (jf.contains(key))
+ {
+ fm_soft_assert(jf[key].is_object());
+ auto& index = val.frameset_indexes[i];
+ fm_soft_assert(index == (uint8_t)-1);
+ index = count++;
+ }
+ }
+ fm_soft_assert(count > 0);
+ fm_soft_assert(count == jf.size());
+
+ val.framesets = std::make_unique<wall_frame_set[]>(count);
+ val.frameset_count = count;
+}
+
} // namespace
+void Serialize::wall_test::read_atlas_header(const nlohmann::json& j, wall_atlas_def& val)
+{
+ val = {};
+ val.info = { std::string(j["name"s]), j["depth"], };
+ val.frame_count = (uint32_t)j["frames"s].size();
+ read_framesets(j["framesets"s], val);
+}
+
} // namespace floormat
namespace nlohmann {
diff --git a/serialize/wall-atlas.hpp b/serialize/wall-atlas.hpp
index 5e454f87..f8f3110b 100644
--- a/serialize/wall-atlas.hpp
+++ b/serialize/wall-atlas.hpp
@@ -13,3 +13,9 @@ struct adl_serializer<std::shared_ptr<floormat::wall_atlas>>
};
} // namespace nlohmann
+
+namespace floormat::Serialize::wall_test {
+
+void read_atlas_header(const nlohmann::json& j, wall_atlas_def& val);
+
+} // namespace floormat::Serialize::wall_test
diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp
index 685125cd..be4010c7 100644
--- a/src/wall-atlas.cpp
+++ b/src/wall-atlas.cpp
@@ -8,6 +8,7 @@ namespace floormat {
size_t wall_atlas::enum_to_index(enum rotation r)
{
+ static_assert(rotation_COUNT == rotation{8});
fm_debug_assert(r < rotation_COUNT);
auto x = uint8_t(r);
@@ -16,19 +17,27 @@ size_t wall_atlas::enum_to_index(enum rotation r)
}
wall_atlas::wall_atlas(wall_info info, const ImageView2D& image,
- ArrayView<const wall_frame_set> rotations,
- ArrayView<const wall_frame> frames) :
- _array{NoInit, frames.size()}, _info(std::move(info))
+ Array<wall_frame> frames,
+ std::unique_ptr<wall_frame_set[]> framesets,
+ uint8_t frameset_count,
+ std::array<uint8_t, 4> frameset_indexes) :
+ _framesets{std::move(framesets)}, _frame_array{std::move(frames)}, _info(std::move(info)),
+ _frameset_indexes{frameset_indexes},
+ _frameset_count{(uint8_t)frameset_count}
{
- fm_assert(info.depth > 0);
- fm_assert(rotations.size() <= _rotations.size());
- _rotation_count = (uint8_t)rotations.size();
- for (auto i = 0uz; const auto& fr : frames)
- _array[i++] = fr;
- for (auto i = 0uz; const auto& r : rotations)
- _rotations[i++] = r;
-
- _texture.setLabel(_name)
+ { fm_assert(frameset_count <= 4);
+ uint8_t counts[4] = {}, total = 0;
+
+ for (auto i = 0uz; i < frameset_count; i++)
+ if (frameset_indexes[i] != (uint8_t)-1)
+ {
+ fm_assert(++counts[i] == 1);
+ total++;
+ }
+ fm_assert(total == frameset_count);
+ }
+
+ _texture.setLabel(_info.name)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setMinificationFilter(GL::SamplerFilter::Linear)
@@ -40,16 +49,21 @@ wall_atlas::wall_atlas(wall_info info, const ImageView2D& image,
wall_atlas::wall_atlas() = default;
wall_atlas::~wall_atlas() noexcept = default;
-const wall_frame_set& wall_atlas::frameset(size_t i) const { return _rotations[i]; }
-const wall_frame_set& wall_atlas::frameset(enum rotation r) const { return frameset(enum_to_index(r)); }
-const ArrayView<const wall_frame> wall_atlas::array() const { return _array; }
+ArrayView<const wall_frame> wall_atlas::frame_array() const { return _frame_array; }
StringView wall_atlas::name() const { return _info.name; }
+const wall_frame_set& wall_atlas::frameset(enum rotation r) const { return frameset(enum_to_index(r)); }
+
+const wall_frame_set& wall_atlas::frameset(size_t i) const
+{
+ fm_assert(i < 4 && _frameset_indexes[i] != (uint8_t)-1);
+ return _framesets[i];
+}
ArrayView<const wall_frame> wall_frames::items(const wall_atlas& a) const
{
- fm_assert(index < a.array().size());
- fm_debug_assert(count != (uint32_t)-1);
- return { a.array() + index, count };
+ auto sz = a.frame_array().size(); (void)sz;
+ fm_assert(index < sz && index + count <= sz);
+ return { a.frame_array() + index, count };
}
} // namespace floormat
diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp
index 4414ac3f..aa18c0bc 100644
--- a/src/wall-atlas.hpp
+++ b/src/wall-atlas.hpp
@@ -1,6 +1,8 @@
#pragma once
+#include "compat/defs.hpp"
#include "src/rotation.hpp"
#include <array>
+#include <memory>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/String.h>
#include <Magnum/Math/Vector2.h>
@@ -20,7 +22,7 @@ struct wall_frames
{
ArrayView<const wall_frame> items(const wall_atlas& a) const;
- uint32_t index = (uint32_t)-1, count = (uint32_t)-1; // not serialized
+ uint32_t index = (uint32_t)-1, count = 0;
Vector2ui pixel_size;
Color4 tint_mult{1,1,1,1};
@@ -39,30 +41,44 @@ struct wall_frame_set
struct wall_info
{
String name = "(unnamed)"_s;
- float depth = 1;
+ unsigned depth = 0;
+};
+
+struct wall_atlas_def
+{
+ wall_info info;
+ std::unique_ptr<wall_frame_set[]> framesets;
+ std::array<uint8_t, 4> frameset_indexes = {255, 255, 255, 255};
+ uint8_t frameset_count = 0;
+
+ Array<wall_frame> array;
+ uint32_t frame_count = 0;
};
struct wall_atlas final
{
+ fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(wall_atlas);
wall_atlas();
- wall_atlas(wall_info info,
- const ImageView2D& image,
- ArrayView<const wall_frame_set> rotations,
- ArrayView<const wall_frame> frames);
~wall_atlas() noexcept;
+ wall_atlas(wall_info info, const ImageView2D& image,
+ Array<wall_frame> frames,
+ std::unique_ptr<wall_frame_set[]> framesets,
+ uint8_t frameset_count,
+ std::array<uint8_t, 4> frameset_indexes);
+
static size_t enum_to_index(enum rotation x);
const wall_frame_set& frameset(size_t i) const;
const wall_frame_set& frameset(enum rotation r) const;
- const ArrayView<const wall_frame> array() const;
+ ArrayView<const wall_frame> frame_array() const;
StringView name() const;
private:
- String _name;
- std::array<wall_frame_set, 4> _rotations;
- Array<wall_frame> _array;
- GL::Texture2D _texture;
+ std::unique_ptr<wall_frame_set[]> _framesets;
+ Array<wall_frame> _frame_array;
wall_info _info;
- uint8_t _rotation_count = 0;
+ GL::Texture2D _texture;
+ std::array<uint8_t, 4> _frameset_indexes;
+ uint8_t _frameset_count = 0;
};
} // namespace floormat
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2c1ce2ff..897268f3 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -26,3 +26,9 @@ file(GLOB files "save/*.dat" CONFIGURE_ARGS)
foreach(file ${files})
install(FILES "${file}" DESTINATION "${save-dir}")
endforeach()
+
+set(json-dir "${CMAKE_BINARY_DIR}/test/json")
+file(GLOB files "json/*.json" CONFIGURE_ARGS)
+foreach(file ${files})
+ install(FILES "${file}" DESTINATION "${json-dir}")
+endforeach()
diff --git a/test/json/frameset-header.json b/test/json/frameset-header.json
new file mode 100644
index 00000000..8b32cabc
--- /dev/null
+++ b/test/json/frameset-header.json
@@ -0,0 +1,9 @@
+{
+ "name": "foo",
+ "depth": 42,
+ "framesets": {
+ "w": {},
+ "n": {}
+ },
+ "frames": []
+}
diff --git a/test/wall-atlas.cpp b/test/wall-atlas.cpp
index 61f252b7..b1cdd8d6 100644
--- a/test/wall-atlas.cpp
+++ b/test/wall-atlas.cpp
@@ -1,16 +1,54 @@
#include "test/app.hpp"
#include "src/wall-atlas.hpp"
+#include "serialize/wall-atlas.hpp"
+#include "serialize/json-helper.hpp"
+#include "loader/loader.hpp"
+#include <algorithm>
+#include <Corrade/Utility/Path.h>
namespace floormat {
+namespace ranges = std::ranges;
+namespace test = floormat::Serialize::wall_test;
+
namespace {
+void test_atlas_header(StringView path)
+{
+ auto j = json_helper::from_json_(Path::join(path, "frameset-header.json"_s));
+ wall_atlas_def def;
+ test::read_atlas_header(j, def);
+
+ fm_assert(def.info.name == "foo"_s);
+ fm_assert(def.info.depth == 42);
+ fm_assert(def.frameset_count == 2);
+
+ constexpr auto none = (uint8_t)-1;
+ enum : uint8_t { N, E, S, W, };
+
+ fm_assert(def.frameset_indexes[N] == 0 || def.frameset_indexes[N] == 1);
+ fm_assert(def.frameset_indexes[E] == none);
+ fm_assert(def.frameset_indexes[S] == none);
+ if (def.frameset_indexes[N] == 0)
+ fm_assert(def.frameset_indexes[W] == 1);
+ else if (def.frameset_indexes[N] == 1)
+ fm_assert(def.frameset_indexes[W] == 0);
+
+ std::fputs("", stdout);
+}
} // namespace
void test_app::test_wall_atlas()
{
+ fm_assert(Path::exists(Path::join(loader.TEMP_PATH, "CMakeCache.txt")));
+ const auto path = Path::join(loader.TEMP_PATH, "test/json"_s);
+ fm_assert(Path::isDirectory(path));
+
+ test_atlas_header(path);
}
+
+
} // namespace floormat
diff --git a/wall-tileset-tool/main.cpp b/wall-tileset-tool/main.cpp
index 511ef4c2..5863bdf4 100644
--- a/wall-tileset-tool/main.cpp
+++ b/wall-tileset-tool/main.cpp
@@ -11,6 +11,7 @@
#include <Corrade/Containers/TripleStl.h>
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/Arguments.h>
+#include <nlohmann/json.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
@@ -22,6 +23,18 @@ using namespace std::string_literals;
namespace {
+wall_atlas_def read_atlas_def(const nlohmann::json& j)
+{
+ auto val = wall_atlas_def{};
+ auto& info = val.info;
+ info.name = std::string(j["name"s]);
+ info.depth = j["depth"s];
+
+ fm_assert(loader.check_atlas_name(info.name));
+
+ return val;
+}
+
struct options
{
String input_dir, input_file, output_dir;