diff options
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | anim-crop-tool/CMakeLists.txt | 5 | ||||
-rw-r--r-- | anim-crop-tool/atlas.cpp | 4 | ||||
-rw-r--r-- | anim-crop-tool/atlas.hpp | 8 | ||||
-rw-r--r-- | anim-crop-tool/main.cpp | 35 | ||||
-rw-r--r-- | anim/CMakeLists.txt | 12 | ||||
-rw-r--r-- | serialize/CMakeLists.txt | 5 | ||||
-rw-r--r-- | serialize/anim.cpp (renamed from anim/serialize.cpp) | 12 | ||||
-rw-r--r-- | serialize/anim.hpp (renamed from anim/serialize.hpp) | 8 | ||||
-rw-r--r-- | serialize/helper.hpp (renamed from json-magnum.hpp) | 50 | ||||
-rw-r--r-- | serialize/vector.hpp | 41 |
11 files changed, 108 insertions, 80 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 41ac4b9a..5e5ef563 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,10 +60,10 @@ if(NOT BOOTSTRAP_DEPENDS) include_directories(.) add_subdirectory(anim-crop-tool) - add_subdirectory(anim) + add_subdirectory(serialize) corrade_add_resource(game_RESOURCES resources.conf) - file(GLOB sources "*.cpp" "shaders/*.cpp" CONFIGURE_ARGS) + file(GLOB sources "*.cpp" "shaders/*.cpp" "serialize/*.cpp" CONFIGURE_ARGS) add_executable(${PROJECT_NAME} WIN32 "${sources}" "${game_RESOURCES}") target_link_libraries(${PROJECT_NAME} PRIVATE @@ -72,7 +72,9 @@ if(NOT BOOTSTRAP_DEPENDS) Magnum::Magnum Magnum::Shaders Magnum::Trade - MagnumIntegration::Glm) + MagnumIntegration::Glm + nlohmann_json::nlohmann_json + ) target_include_directories(${PROJECT_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) target_include_directories(${PROJECT_NAME} PRIVATE magnum-integration/src) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) diff --git a/anim-crop-tool/CMakeLists.txt b/anim-crop-tool/CMakeLists.txt index 7b6d22a8..76304068 100644 --- a/anim-crop-tool/CMakeLists.txt +++ b/anim-crop-tool/CMakeLists.txt @@ -2,8 +2,9 @@ find_package(OpenCV QUIET REQUIRED COMPONENTS core imgcodecs imgproc) set(self "${PROJECT_NAME}-anim-crop-tool") include_directories(SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS}) -link_libraries(Corrade::Utility) -link_libraries(${PROJECT_NAME}-anim) +link_libraries(Corrade::Utility Magnum::Magnum) +link_libraries("${PROJECT_NAME}-serialize") +link_libraries(opencv_imgproc opencv_imgcodecs opencv_core) file(GLOB sources "*.cpp" CONFIGURE_ARGS) add_executable(${self} ${sources}) diff --git a/anim-crop-tool/atlas.cpp b/anim-crop-tool/atlas.cpp index 8c43d64f..4b005d60 100644 --- a/anim-crop-tool/atlas.cpp +++ b/anim-crop-tool/atlas.cpp @@ -1,10 +1,12 @@ #include "atlas.hpp" -#include "anim/serialize.hpp" +#include "serialize/anim.hpp" #include "compat/assert.hpp" #include <filesystem> #include <opencv2/imgcodecs.hpp> +using namespace Magnum::Examples::Serialize; + void anim_atlas_row::add_entry(const anim_atlas_entry& x) { auto& frame = *x.frame; diff --git a/anim-crop-tool/atlas.hpp b/anim-crop-tool/atlas.hpp index 66bddb5d..be74b40a 100644 --- a/anim-crop-tool/atlas.hpp +++ b/anim-crop-tool/atlas.hpp @@ -5,10 +5,12 @@ #include <Magnum/Math/Vector2.h> #include <opencv2/core/mat.hpp> -struct anim_frame; - namespace std::filesystem { class path; } +namespace Magnum::Examples::Serialize { + +struct anim_frame; + struct anim_atlas_entry { anim_frame* frame; @@ -35,3 +37,5 @@ public: Magnum::Vector2i size() const noexcept; [[nodiscard]] bool dump(const std::filesystem::path& filename) const; }; + +} // namespace Magnum::Examples::Serialize diff --git a/anim-crop-tool/main.cpp b/anim-crop-tool/main.cpp index 600688c1..be3f7469 100644 --- a/anim-crop-tool/main.cpp +++ b/anim-crop-tool/main.cpp @@ -1,9 +1,10 @@ #include "atlas.hpp" -#include "anim/serialize.hpp" +#include "serialize/anim.hpp" #include "compat/defs.hpp" #include "compat/sysexits.hpp" #include "compat/assert.hpp" +#include <cerrno> #include <cmath> #include <cstring> @@ -26,6 +27,8 @@ using Corrade::Utility::Debug; using std::filesystem::path; +using namespace Magnum::Examples::Serialize; + struct options { double scale = 0; @@ -65,7 +68,7 @@ static bool load_file(anim_group& group, options& opts, anim_atlas& atlas, const cv::Mat mat = cv::imread(filename.string(), cv::IMREAD_UNCHANGED); if (mat.empty() || mat.type() != CV_8UC4) { - Error{} << "failed to load" << filename << "as RGBA32 image"; + Error{} << "error: failed to load" << filename << "as RGBA32 image"; return cv::Mat4b{}; } return cv::Mat4b(std::move(mat)); @@ -78,7 +81,7 @@ static bool load_file(anim_group& group, options& opts, anim_atlas& atlas, const if (!bounds_ok) { - Error{} << "no valid image data in" << filename; + Error{} << "error: no valid image data in" << filename; return false; } @@ -101,7 +104,7 @@ static bool load_file(anim_group& group, options& opts, anim_atlas& atlas, const if (size.width < dest_size.width || size.height < dest_size.height) { - Error{} << "refusing to upscale image" << filename; + Error{} << "error: refusing to upscale image" << filename; return false; } @@ -125,7 +128,7 @@ static bool load_directory(anim_group& group, options& opts, anim_atlas& atlas) if (std::error_code ec; !std::filesystem::exists(input_dir/".", ec)) { - Error{Error::Flag::NoSpace} << "can't open directory " << input_dir << ": " << ec.message(); + Error{} << "error: can't open directory" << input_dir << ":" << ec.message(); return false; } @@ -148,9 +151,8 @@ static bool load_directory(anim_group& group, options& opts, anim_atlas& atlas) opts.nframes = max-1; else if (opts.nframes != max-1) { - Error{Error::Flag::NoSpace} << "wrong frame count for direction '" - << group.name << "' -- " << max-1 - << " should be " << opts.nframes; + Error{} << "error: wrong frame count for direction" << group.name << ":" + << max-1 << "should be" << opts.nframes; return false; } @@ -203,6 +205,7 @@ static std::tuple<options, Arguments, bool> parse_cmdline(int argc, const char* opts.width = w; if (int h = args.value<int>("height"); h != 0) opts.height = h; + opts.output_dir = args.value<std::string>("output"); opts.input_file = args.value<std::string>("input"); opts.input_dir = opts.input_file.parent_path(); @@ -248,7 +251,7 @@ int main(int argc, char** argv) if (!check_atlas_name(anim_info.name)) { - Error{Error::Flag::NoSpace} << "atlas name '" << anim_info.name << "' contains invalid characters"; + Error{} << "error: atlas name" << anim_info.name << "contains invalid characters"; return EX_DATAERR; } @@ -260,7 +263,7 @@ int main(int argc, char** argv) if (!(opts.width ^ opts.height) || opts.width < 0 || opts.height < 0) { - Error{} << "exactly one of --width, --height must be specified"; + Error{} << "error: exactly one of --width, --height must be specified"; return usage(args); } @@ -270,8 +273,18 @@ int main(int argc, char** argv) if (!load_directory(group, opts, atlas)) return EX_DATAERR; - if (!atlas.dump(opts.output_dir/(anim_info.name + ".png"))) + if (std::error_code ec{}; !std::filesystem::exists(opts.output_dir/".", ec) && + !std::filesystem::create_directory(opts.output_dir, ec)) { + Error{} << "error: failed to create output directory" + << opts.output_dir << ":" << ec.message(); return EX_CANTCREAT; + } + + if (auto pathname = opts.output_dir/(anim_info.name + ".png"); !atlas.dump(pathname)) { + Error{} << "error: failed writing image to" << pathname << ":" + << std::strerror(errno); // NOLINT(concurrency-mt-unsafe) + return EX_CANTCREAT; + } if (!anim_info.to_json(opts.output_dir/(anim_info.name + ".json"))) return EX_CANTCREAT; diff --git a/anim/CMakeLists.txt b/anim/CMakeLists.txt deleted file mode 100644 index bc148a06..00000000 --- a/anim/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -find_package(OpenCV QUIET REQUIRED COMPONENTS core imgcodecs imgproc) -find_package(nlohmann_json QUIET REQUIRED) - -set(self "${PROJECT_NAME}-anim") - -include_directories(SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS}) -link_libraries(opencv_imgproc opencv_imgcodecs opencv_core) -link_libraries(Magnum::Magnum nlohmann_json::nlohmann_json) - -file(GLOB sources "*.cpp" CONFIGURE_ARGS) -add_library(${self} STATIC ${sources}) - diff --git a/serialize/CMakeLists.txt b/serialize/CMakeLists.txt new file mode 100644 index 00000000..e695aff2 --- /dev/null +++ b/serialize/CMakeLists.txt @@ -0,0 +1,5 @@ +find_package(nlohmann_json QUIET REQUIRED) +set(self "${PROJECT_NAME}-serialize") +link_libraries(Magnum::Magnum nlohmann_json::nlohmann_json) +file(GLOB sources "*.cpp" CONFIGURE_ARGS) +add_library(${self} STATIC ${sources}) diff --git a/anim/serialize.cpp b/serialize/anim.cpp index 8c027d9c..c65c24a6 100644 --- a/anim/serialize.cpp +++ b/serialize/anim.cpp @@ -1,11 +1,13 @@ -#include "serialize.hpp" +#include "serialize/vector.hpp" +#include "serialize/helper.hpp" +#include "serialize/anim.hpp" +#include <tuple> +#include <filesystem> #include <Corrade/Utility/Debug.h> #include <Corrade/Utility/DebugStl.h> -#include "json-magnum.hpp" - -using Corrade::Utility::Error; +namespace Magnum::Examples::Serialize { #if defined __clang__ || defined __CLION_IDE__ # pragma clang diagnostic push @@ -30,3 +32,5 @@ bool anim::to_json(const std::filesystem::path& pathname) const noexcept { return json_helper<anim>::to_json(*this, pathname); } + +} // namespace Magnum::Examples::Serialize diff --git a/anim/serialize.hpp b/serialize/anim.hpp index 3e039a96..f03e3c8c 100644 --- a/anim/serialize.hpp +++ b/serialize/anim.hpp @@ -1,14 +1,17 @@ #pragma once -#include <string> +#include <tuple> #include <array> #include <vector> +#include <string> #include <Magnum/Magnum.h> #include <Magnum/Math/Vector2.h> namespace std::filesystem { class path; } +namespace Magnum::Examples::Serialize { + struct anim_frame final { Magnum::Vector2i ground, offset, size; @@ -39,3 +42,6 @@ struct anim final int width = 0, height = 0; int actionframe = -1, fps = default_fps; }; + +} // namespace Magnum::Examples::Serialize + diff --git a/json-magnum.hpp b/serialize/helper.hpp index bcd17e0a..f16ed60c 100644 --- a/json-magnum.hpp +++ b/serialize/helper.hpp @@ -1,48 +1,10 @@ #pragma once - -#include <cstdio> -#include <string> -#include <utility> +#include <tuple> #include <fstream> #include <exception> +#include <filesystem> #include <nlohmann/json.hpp> -#include <Corrade/Utility/Debug.h> #include <Corrade/Utility/DebugStl.h> -#include <Magnum/Magnum.h> -#include <Magnum/Math/Vector2.h> - -namespace nlohmann { - -template<> -struct adl_serializer<Magnum::Vector2i> final { - static void to_json(json& j, const Magnum::Vector2i& x); - static void from_json(const json& j, Magnum::Vector2i& x); -}; - -void adl_serializer<Magnum::Vector2i>::to_json(json& j, const Magnum::Vector2i& val) -{ - char buf[64]; - snprintf(buf, sizeof(buf), "%d x %d", val[0], val[1]); - j = buf; -} - -void adl_serializer<Magnum::Vector2i>::from_json(const json& j, Magnum::Vector2i& val) -{ - std::string str = j; - int x = 0, y = 0, n = 0; - int ret = std::sscanf(str.c_str(), "%d x %d%n", &x, &y, &n); - if (ret != 2 || (std::size_t)n != str.size()) - { - std::string msg; msg.reserve(64 + str.size()); - msg += "failed to parse string '"; - msg += str; - msg += "' as Magnum::Vector2i"; - throw std::invalid_argument(msg); - } - val = { x, y }; -} - -} // namespace nlohmann template<typename t> struct json_helper final { @@ -59,7 +21,7 @@ std::tuple<t, bool> json_helper<t>::from_json(const std::filesystem::path& pathn try { s.open(pathname, std::ios_base::in); } catch (const std::ios::failure& e) { - Error{Error::Flag::NoSpace} << "failed to open " << pathname << ": " << e.what(); + Error{Error::Flag::NoSpace} << "failed to open '" << pathname << "': " << e.what(); return { {}, false }; } t ret; @@ -69,7 +31,7 @@ std::tuple<t, bool> json_helper<t>::from_json(const std::filesystem::path& pathn using nlohmann::from_json; from_json(j, ret); } catch (const std::exception& e) { - Error{Error::Flag::NoSpace} << "failed to parse " << pathname << ": " << e.what(); + Error{Error::Flag::NoSpace} << "failed to parse '" << pathname << "': " << e.what(); return { {}, false }; } return { std::move(ret), true }; @@ -86,13 +48,13 @@ bool json_helper<t>::to_json(const t& self, const std::filesystem::path& pathnam try { s.open(pathname, std::ios_base::out | std::ios_base::trunc); } catch (const std::ios::failure& e) { - Error{} << "failed to open" << pathname << "for writing:" << e.what(); + Error{Error::Flag::NoSpace} << "failed to open '" << pathname << "' for writing: " << e.what(); return false; } s << j.dump(4); s.flush(); } catch (const std::exception& e) { - Error{Error::Flag::NoSpace} << "failed writing to " << pathname << ": " << e.what(); + Error{Error::Flag::NoSpace} << "failed writing to '" << pathname << "': " << e.what(); return false; } diff --git a/serialize/vector.hpp b/serialize/vector.hpp new file mode 100644 index 00000000..39924a9b --- /dev/null +++ b/serialize/vector.hpp @@ -0,0 +1,41 @@ +#include <cstdio> +#include <string> +#include <exception> +#include <Magnum/Magnum.h> +#include <Magnum/Math/Vector2.h> +#include <nlohmann/json.hpp> + +namespace nlohmann { + +template<typename t> +struct adl_serializer<Magnum::Math::Vector2<t>> final { + static void to_json(json& j, const Magnum::Math::Vector2<t>& x); + static void from_json(const json& j, Magnum::Math::Vector2<t>& x); +}; + +template<typename t> +void adl_serializer<Magnum::Math::Vector2<t>>::to_json(json& j, const Magnum::Math::Vector2<t>& val) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%d x %d", val[0], val[1]); + j = buf; +} + +template<typename t> +void adl_serializer<Magnum::Math::Vector2<t>>::from_json(const json& j, Magnum::Math::Vector2<t>& val) +{ + std::string str = j; + int x = 0, y = 0, n = 0; + int ret = std::sscanf(str.c_str(), "%d x %d%n", &x, &y, &n); + if (ret != 2 || (std::size_t)n != str.size()) + { + std::string msg; msg.reserve(64 + str.size()); + msg += "failed to parse string '"; + msg += str; + msg += "' as Magnum::Vector2i"; + throw std::invalid_argument(msg); + } + val = { x, y }; +} + +} // namespace nlohmann |