summaryrefslogtreecommitdiffhomepage
path: root/wall-tileset-tool/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wall-tileset-tool/main.cpp')
-rw-r--r--wall-tileset-tool/main.cpp121
1 files changed, 83 insertions, 38 deletions
diff --git a/wall-tileset-tool/main.cpp b/wall-tileset-tool/main.cpp
index 38697d9c..c9bb3a72 100644
--- a/wall-tileset-tool/main.cpp
+++ b/wall-tileset-tool/main.cpp
@@ -5,6 +5,7 @@
#include "compat/format.hpp"
#include "compat/debug.hpp"
#include "src/wall-atlas.hpp"
+#include "src/tile-defs.hpp"
#include "serialize/wall-atlas.hpp"
//#include "serialize/json-helper.hpp"
#include "loader/loader.hpp"
@@ -40,11 +41,6 @@ const Direction& get_direction(const wall_atlas_def& atlas, size_t i)
return atlas.direction_array[idx.val];
}
-Direction& get_direction(wall_atlas_def& atlas, size_t i)
-{
- return const_cast<Direction&>(get_direction(const_cast<const wall_atlas_def&>(atlas), i));
-}
-
template<typename Fmt, typename... Xs>
auto asformat(Fmt&& fmt, Xs&&... args)
{
@@ -90,40 +86,62 @@ bool convert_to_bgra32(const cv::Mat& src, cv::Mat4b& dest)
}
}
-Vector2ui mat_size(const cv::Mat& mat)
-{
- return { (unsigned)mat.cols, (unsigned)mat.rows };
-}
-
bool save_image(state st)
{
- const auto count = st.frames.size();
- fm_assert(count);
-
- for (auto i = 1uz; i < count; i++)
- fm_assert(mat_size(st.frames[i].mat).y() == mat_size(st.frames[0].mat).y());
+ fm_assert(st.new_atlas.frames.empty());
+ uint32_t max_height = 0;
+ for (const auto& group : st.groups)
+ {
+ const auto expected_size = wall_atlas::expected_size(st.new_atlas.header.depth, group.G);
+ max_height = std::max(max_height, expected_size.y());
+ }
+ fm_assert(max_height > 0);
+ fm_assert(max_height == (uint32_t)iTILE_SIZE.z()); // todo?
- size_t total_width = 0;
- for (const auto& x : st.frames)
- total_width += mat_size(x.mat).x();
- size_t num_rows = (total_width + max_image_dimension - 1) / max_image_dimension;
- fm_assert(num_rows > 0);
- fm_assert(num_rows == 1); // todo
+ uint32_t xpos = 0;
+ Vector2ui max;
+ for (auto& group : st.groups)
+ {
+ const auto size = wall_atlas::expected_size(st.new_atlas.header.depth, group.G);
+ const auto width = size.x(), height = size.y();
+ uint32_t ypos = 0;
+ bool started = false;
+ for (auto& frame : group.frames)
+ {
+ frame.offset = {xpos, ypos};
+ max = Math::max(max, frame.offset + size);
+ started = true;
+ fm_assert(max <= Vector2ui{(unsigned)max_image_dimension});
+ fm_assert(frame.size == size);
+ if (ypos + height*2 <= max_height)
+ ypos += height;
+ else
+ {
+ ypos = 0;
+ xpos += width;
+ started = false;
+ }
+ }
+ if (started)
+ xpos += width;
+ }
+ fm_assert(max.product() > 0);
- st.dest.create((int)mat_size(st.frames[0].mat).y(), (int)total_width);
- st.dest.setTo(cv::Scalar{0, 0, 0, 0});
+ st.dest.create((int)max.y(), (int)max.x());
+ st.dest.setTo(cv::Scalar{255, 0, 255, 0});
- unsigned xpos = 0;
- for (auto& x : st.frames)
+ for (const auto& group : st.groups)
{
- const auto& src = x.mat;
- x.size = mat_size(src);
- x.offset = {(unsigned)xpos, 0};
- auto rect = cv::Rect{(int)xpos, 0, (int)x.size.x(), (int)x.size.y()};
- xpos += x.size.x();
- src.copyTo(st.dest(rect));
- st.new_atlas.frames.push_back({.offset = x.offset, .size = x.size});
+ for (const auto& frame : group.frames)
+ {
+ //Debug{} << "g" << (int)group.G << frame.offset << frame.size;
+ auto rect = cv::Rect{(int)frame.offset.x(), (int)frame.offset.y(),
+ (int)frame.size.x(), (int)frame.size.y()};
+ frame.mat.copyTo(st.dest(rect));
+ st.new_atlas.frames.push_back({.offset = frame.offset, .size = frame.size});
+ }
}
+
auto filename = ""_s.join({Path::join(st.opts.output_dir, st.new_atlas.header.name), ".png"_s});
if (!st.opts.use_alpha)
{
@@ -139,6 +157,8 @@ bool save_image(state st)
bool save_json(state st)
{
using namespace floormat::Wall::detail;
+ fm_assert(!st.new_atlas.frames.empty());
+ fm_assert(st.new_atlas.header.depth > 0);
auto filename = ""_s.join({Path::join(st.opts.output_dir, st.new_atlas.header.name), ".json"_s});
st.new_atlas.serialize(filename);
return true;
@@ -160,8 +180,16 @@ bool do_group(state st, size_t i, size_t j, Group& new_group)
DBG << " group" << quoted2(group_name);
fm_debug_assert(expected_size > Vector2ui{0});
fm_assert(Math::max(expected_size.x(), expected_size.y()) < max_image_dimension);
+ fm_assert((size_t)st.groups.at(j).G == j);
+
+ auto& frames = [&] -> auto&& {
+ for (auto& g : st.groups)
+ if ((size_t)g.G == j)
+ return g.frames;
+ fm_abort("can't find ground '%d'", (int)j);
+ }();
- uint32_t count = 0, start = (uint32_t)st.frames.size();
+ auto count = 0uz, start = st.n_frames;
new_group = old_group;
new_group.is_defined = true;
new_group.pixel_size = Vector2ui(expected_size);
@@ -171,13 +199,15 @@ bool do_group(state st, size_t i, size_t j, Group& new_group)
auto filename = asformat("{}/{:04}.png"_cf, path, count+1);
if (!Path::exists(filename))
break;
- count++;
if (Path::isDirectory(filename)) [[unlikely]]
{
ERR << "fatal: path" << quoted(filename) << "is a directory!";
return false;
}
+ count++;
+ st.n_frames++;
+
cv::Mat mat = cv::imread(filename, cv::IMREAD_ANYCOLOR), mat2;
if ((Group_)j == Group_::top)
{
@@ -210,7 +240,10 @@ bool do_group(state st, size_t i, size_t j, Group& new_group)
return false;
}
- st.frames.push_back({.mat = std::move(buf)});
+ frames.push_back({
+ .mat = std::move(buf),
+ .size = {(unsigned)mat.cols, (unsigned)mat.rows},
+ });
}
if (count == 0)
@@ -221,7 +254,7 @@ bool do_group(state st, size_t i, size_t j, Group& new_group)
DBG << " " << Debug::nospace << count << (count == 1 ? "frame" : "frames");
- fm_assert(start + count == st.frames.size());
+ fm_assert(start + count == st.n_frames);
new_group.count = count;
new_group.index = start;
@@ -363,15 +396,27 @@ int main(int argc, char** argv)
auto old_atlas = wall_atlas_def::deserialize(opts.input_file);
auto new_atlas = wall_atlas_def{};
- auto frames = std::vector<frame>{}; frames.reserve(64);
auto dest = cv::Mat4b{};
auto error = EX_DATAERR;
+ size_t n_frames = 0;
+
+ auto groups = std::vector<group>{};
+ groups.reserve(std::size(Wall::Direction::groups));
+
+ for (auto [name, ptr, val] : Wall::Direction::groups)
+ {
+ groups.push_back({
+ .frames = std::vector<frame>{},
+ .G = val,
+ });
+ }
auto st = state {
.opts = opts,
.old_atlas = old_atlas,
.new_atlas = new_atlas,
- .frames = frames,
+ .groups = groups,
+ .n_frames = n_frames,
.dest = dest,
.error = error,
};