summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compat/assert.hpp16
-rw-r--r--compat/prelude.hpp7
-rw-r--r--serialize/wall-atlas.cpp17
-rw-r--r--serialize/wall-atlas.hpp4
-rw-r--r--src/wall-atlas.hpp24
-rw-r--r--wall-tileset-tool/main.cpp143
6 files changed, 123 insertions, 88 deletions
diff --git a/compat/assert.hpp b/compat/assert.hpp
index 73e1d376..550933fa 100644
--- a/compat/assert.hpp
+++ b/compat/assert.hpp
@@ -92,14 +92,14 @@
{ \
if (a != b) [[unlikely]] \
{ \
- DBG_nospace << Debug::color(Debug::Color::Magenta) \
- << "fatal:" \
- << Debug::resetColor << " " \
- << "Equality assertion failed at " \
- << __FILE__ << ":" << __LINE__; \
- DBG_nospace << #__VA_ARGS__; \
- DBG_nospace << " expected: " << a; \
- DBG_nospace << " actual: " << b; \
+ FATAL_nospace << Debug::color(Debug::Color::Magenta) \
+ << "fatal:" \
+ << Debug::resetColor << " " \
+ << "Equality assertion failed at " \
+ << __FILE__ << ":" << __LINE__; \
+ FATAL_nospace << #__VA_ARGS__; \
+ FATAL_nospace << " expected: " << a; \
+ FATAL_nospace << " actual: " << b; \
fm_EMIT_ABORT(); \
} \
})(__VA_ARGS__)
diff --git a/compat/prelude.hpp b/compat/prelude.hpp
index 443ab382..973e99d7 100644
--- a/compat/prelude.hpp
+++ b/compat/prelude.hpp
@@ -6,7 +6,14 @@
#include <Magnum/Magnum.h>
#define DBG_nospace (::Corrade::Utility::Debug{::Corrade::Utility::Debug::Flag::NoSpace})
+#define WARNING_nospace (::Corrade::Utility::Warning{::Corrade::Utility::Debug::Flag::NoSpace})
+#define ERROR_nospace (::Corrade::Utility::Error{::Corrade::Utility::Debug::Flag::NoSpace})
+#define FATAL_nospace (::Corrade::Utility::Fatal{::Corrade::Utility::Debug::Flag::NoSpace})
+
#define DBG (::Corrade::Utility::Debug{})
+#define WARNING (::Corrade::Utility::Warning{})
+#define ERROR (::Corrade::Utility::Error{})
+#define FATAL (::Corrade::Utility::Fatal{})
#if !(defined __cpp_size_t_suffix || defined _MSC_VER && _MSVC_LANG < 202004)
#ifdef _MSC_VER
diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp
index 28d54a0c..d2f4fa77 100644
--- a/serialize/wall-atlas.cpp
+++ b/serialize/wall-atlas.cpp
@@ -18,6 +18,7 @@
namespace floormat {
+using namespace floormat::Wall;
using namespace floormat::Wall::detail;
bool wall_atlas_def::operator==(const wall_atlas_def& other) const noexcept
@@ -57,7 +58,7 @@ wall_atlas_def wall_atlas_def::deserialize(StringView filename)
atlas.frames = read_all_frames(jroot);
auto [dirs, dir_indexes] = read_all_directions(jroot);
fm_soft_assert(!dirs.empty());
- fm_soft_assert(dir_indexes != std::array<Wall::DirArrayIndex, 4>{});
+ fm_soft_assert(dir_indexes != std::array<Wall::DirArrayIndex, Direction_COUNT>{});
atlas.direction_array = std::move(dirs);
atlas.direction_map = dir_indexes;
atlas.direction_mask = get_existing_directions(jroot);
@@ -66,7 +67,8 @@ wall_atlas_def wall_atlas_def::deserialize(StringView filename)
}
void wall_atlas_def::serialize(StringView filename, const Info& header, ArrayView<const Frame> frames,
- ArrayView<const Direction> dir_array, std::array<DirArrayIndex, 4> dir_map)
+ ArrayView<const Direction> dir_array,
+ std::array<DirArrayIndex, Direction_COUNT> dir_map)
{
auto jroot = json{};
@@ -201,23 +203,23 @@ Direction read_direction_metadata(const json& jroot, Direction_ dir)
return val;
}
-[[nodiscard]] std::bitset<(size_t)Direction_::COUNT> get_existing_directions(const json& jroot)
+[[nodiscard]] std::bitset<Direction_COUNT> get_existing_directions(const json& jroot)
{
- std::bitset<(size_t)Direction_::COUNT> array{0};
+ std::bitset<Direction_COUNT> array{0};
for (uint8_t i = 0; auto [str, dir] : wall_atlas::directions)
if (jroot.contains(str))
array[i] = true;
return array;
}
-Pair<std::vector<Direction>, std::array<DirArrayIndex, 4>> read_all_directions(const json& jroot)
+Pair<std::vector<Direction>, std::array<DirArrayIndex, Direction_COUNT>> read_all_directions(const json& jroot)
{
size_t count = 0;
for (auto [str, _] : wall_atlas::directions)
if (jroot.contains(str))
count++;
std::vector<Direction> array{count};
- std::array<DirArrayIndex, 4> map = {};
+ std::array<DirArrayIndex, Direction_COUNT> map = {};
for (uint8_t i = 0; auto [str, dir] : wall_atlas::directions)
if (jroot.contains(str))
{
@@ -283,7 +285,8 @@ void write_direction_metadata(json& jdir, const Direction& dir)
if (jdir.contains("top"))
{
json& top = jdir["top"];
- top["pixel-size"] = Math::Vector<2, Int>(top["pixel-size"]).flipped();
+ Vector2i vec = top["pixel-size"];
+ top["pixel-size"] = vec.flipped();
}
}
diff --git a/serialize/wall-atlas.hpp b/serialize/wall-atlas.hpp
index 4e96943d..0d1f80b2 100644
--- a/serialize/wall-atlas.hpp
+++ b/serialize/wall-atlas.hpp
@@ -20,8 +20,8 @@ StringView direction_index_to_name(size_t i);
[[nodiscard]] std::vector<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);
-[[nodiscard]] std::bitset<(size_t)Direction_::COUNT> get_existing_directions(const json& jroot);
-Pair<std::vector<Direction>, std::array<DirArrayIndex, 4>> read_all_directions(const json& jroot);
+[[nodiscard]] std::bitset<Direction_COUNT> get_existing_directions(const json& jroot);
+Pair<std::vector<Direction>, std::array<DirArrayIndex, Direction_COUNT>> read_all_directions(const json& jroot);
Info read_info_header(const json& jroot);
void write_all_frames(json& jroot, ArrayView<const Frame> array);
diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp
index fcad0a8b..60e87286 100644
--- a/src/wall-atlas.hpp
+++ b/src/wall-atlas.hpp
@@ -90,27 +90,23 @@ struct DirArrayIndex {
namespace floormat {
+constexpr inline auto Direction_COUNT = (size_t)Wall::Direction_::COUNT;
+
struct wall_atlas_def final
{
-private:
- using Frame = Wall::Frame;
- using Direction = Wall::Direction;
- using Info = Wall::Info;
- using DirArrayIndex = Wall::DirArrayIndex;
-
-public:
bool operator==(const wall_atlas_def&) const noexcept;
- Info header;
- std::vector<Frame> frames;
- std::vector<Direction> direction_array;
- std::array<DirArrayIndex, 4> direction_map;
- std::bitset<(size_t)Wall::Direction_::COUNT> direction_mask{0};
+ Wall::Info header;
+ std::vector<Wall::Frame> frames;
+ std::vector<Wall::Direction> direction_array;
+ std::array<Wall::DirArrayIndex, Direction_COUNT> direction_map;
+ std::bitset<Direction_COUNT> direction_mask{0};
static wall_atlas_def deserialize(StringView filename);
void serialize(StringView filename) const;
- static void serialize(StringView filename, const Info& header, ArrayView<const Frame> frames,
- ArrayView<const Direction> dir_array, std::array<DirArrayIndex, 4> dir_map);
+ static void serialize(StringView filename, const Wall::Info& header, ArrayView<const Wall::Frame> frames,
+ ArrayView<const Wall::Direction> dir_array,
+ std::array<Wall::DirArrayIndex, Direction_COUNT> dir_map);
};
class wall_atlas final
diff --git a/wall-tileset-tool/main.cpp b/wall-tileset-tool/main.cpp
index ee513bcb..f7c92772 100644
--- a/wall-tileset-tool/main.cpp
+++ b/wall-tileset-tool/main.cpp
@@ -1,6 +1,7 @@
#include "compat/assert.hpp"
#include "compat/sysexits.hpp"
#include "compat/fix-argv0.hpp"
+#include "compat/strerror.hpp"
#include "src/wall-atlas.hpp"
#include "serialize/wall-atlas.hpp"
#include "serialize/json-helper.hpp"
@@ -27,59 +28,11 @@ using namespace floormat::Wall;
namespace {
-struct options
-{
- String input_dir, input_file, output_dir;
-};
-
-std::shared_ptr<wall_atlas> read_from_file(StringView filename)
-{
- using namespace floormat::Wall::detail;
- auto def = wall_atlas_def::deserialize(filename);
-
- const auto jroot = json_helper::from_json_(filename);
- auto header = read_info_header(jroot);
- if (!loader.check_atlas_name(header.name))
- fm_abort("bad atlas name '%s'!", header.name.data());
-
- return {};
-}
-
-inline String fixsep(String str)
-{
-#ifdef _WIN32
- for (char& c : str)
- if (c == '\\')
- c = '/';
-#endif
- return str;
-}
-
-#if 0
-bool make_buffer(cv::Mat4b& buf, const wall_atlas& a, Direction_ dir, Group_ group)
-{
- if (const auto* p = a.group(dir, group))
- {
- auto size = a.expected_size(a.info().depth, group);
- fm_assert(size >= Vector2i{0} && size < Vector2i{1<<16});
- if (buf.cols < size.x() || buf.rows < size.y())
- {
- auto size_ = Vector2i{std::max(size.x(), buf.cols), std::max(size.y(), buf.rows)};
- buf.create(cv::Size{size_.x(), size_.y()});
- fm_debug_assert(size_ >= Vector2i{0} && size_ < Vector2i{1<<16});
- fm_debug_assert(Vector2i{buf.cols, buf.rows} >= size);
- }
- return true;
- }
- return false;
-}
-#endif
-
Vector2i get_buffer_size(const wall_atlas_def& a)
{
Vector2i size;
- for (auto i = 0uz; i < (size_t)Direction_::COUNT; i++)
+ for (auto i = 0uz; i < Direction_COUNT; i++)
{
auto idx = a.direction_map[i];
if (!idx)
@@ -101,14 +54,73 @@ Vector2i get_buffer_size(const wall_atlas_def& a)
return size;
}
+struct options
+{
+ String input_dir, input_file, output_dir;
+};
+
struct state
{
- options opts;
- cv::Mat4b buffer;
- const wall_atlas_def atlas;
- wall_atlas_def new_atlas = atlas;
+ options& opts;
+ cv::Mat4b& buffer;
+ const wall_atlas_def& old_atlas;
+ wall_atlas_def& new_atlas;
+ int& error;
};
+bool do_direction(state& st, Direction_ i)
+{
+ const auto& name = wall_atlas::directions[(size_t)i].name;
+ DBG_nospace << " direction '" << name << "'";
+ auto dir = Path::join(st.opts.input_dir, name);
+ if (!Path::isDirectory(dir))
+ {
+ char errbuf[128];
+ auto error = get_error_string(errbuf);
+ Fatal{Fatal::Flag::NoSpace} << "fatal: direction '" << name
+ << "' has missing directory '" << dir
+ << "': " << error;
+ return false;
+ }
+
+ auto dir_count = st.old_atlas.direction_mask.count();
+ st.new_atlas.direction_array = std::vector<Direction>{dir_count};
+
+
+ return true;
+}
+
+bool do_input_file(state& st)
+{
+ DBG_nospace << "input-file '" << st.old_atlas.header.name << "'";
+
+ fm_assert(!st.buffer.empty());
+ fm_assert(loader.check_atlas_name(st.old_atlas.header.name));
+ fm_assert(st.old_atlas.direction_mask.any());
+
+ st.new_atlas.header = std::move(const_cast<wall_atlas_def&>(st.old_atlas).header);
+
+ for (auto i = 0uz; i < Direction_COUNT; i++)
+ {
+ if (!st.old_atlas.direction_mask[i])
+ continue;
+ if (!do_direction(st, (Direction_)i))
+ return false;
+ }
+
+ return true;
+}
+
+inline String fixsep(String str)
+{
+#ifdef _WIN32
+ for (char& c : str)
+ if (c == '\\')
+ c = '/';
+#endif
+ return str;
+}
+
Triple<options, Arguments, bool> parse_cmdline(int argc, const char* const* argv) noexcept
{
Corrade::Utility::Arguments args{};
@@ -124,6 +136,9 @@ Triple<options, Arguments, bool> parse_cmdline(int argc, const char* const* argv
if (opts.output_dir.isEmpty())
opts.output_dir = opts.input_dir;
+ DBG_nospace << "input-dir" << opts.input_dir;
+ DBG_nospace << "output-dir" << opts.output_dir;
+
if (!Path::exists(opts.input_file))
Error{Error::Flag::NoSpace} << "fatal: input file '" << opts.input_file << "' doesn't exist";
else if (!Path::isDirectory(opts.output_dir))
@@ -141,7 +156,7 @@ Triple<options, Arguments, bool> parse_cmdline(int argc, const char* const* argv
return {};
}
-[[nodiscard]] static int usage(const Arguments& args) noexcept
+[[nodiscard]] int usage(const Arguments& args) noexcept
{
Error{Error::Flag::NoNewlineAtTheEnd} << args.usage();
return EX_USAGE;
@@ -157,13 +172,27 @@ int main(int argc, char** argv)
{
argv[0] = fix_argv0(argv[0]);
auto [opts, args, opts_ok] = parse_cmdline(argc, argv);
+ if (!opts_ok)
+ return usage(args);
+
auto a = wall_atlas_def::deserialize(opts.input_file);
auto buf_size = get_buffer_size(a);
+ auto mat = cv::Mat4b{cv::Size{buf_size.x(), buf_size.y()}};
+ auto new_atlas = wall_atlas_def{};
+ auto error = EX_DATAERR;
+
auto st = state {
- .opts = std::move(opts),
- .buffer = cv::Mat4b{cv::Size{buf_size.x(), buf_size.y()}},
- .atlas = std::move(a)
+ .opts = opts,
+ .buffer = mat,
+ .old_atlas = a,
+ .new_atlas = new_atlas,
+ .error = error,
};
+ if (!do_input_file(st))
+ {
+ fm_assert(error);
+ return error;
+ }
return 0;
}