From 6731ab0243ba437595062558e56b800d5eca9cf5 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 5 Oct 2022 15:47:29 +0200 Subject: a --- CMakeLists.txt | 8 ++-- anim-crop-tool/CMakeLists.txt | 5 ++- anim-crop-tool/atlas.cpp | 4 +- anim-crop-tool/atlas.hpp | 8 +++- anim-crop-tool/main.cpp | 35 ++++++++++----- anim/CMakeLists.txt | 12 ----- anim/serialize.cpp | 32 -------------- anim/serialize.hpp | 41 ----------------- json-magnum.hpp | 100 ------------------------------------------ serialize/CMakeLists.txt | 5 +++ serialize/anim.cpp | 36 +++++++++++++++ serialize/anim.hpp | 47 ++++++++++++++++++++ serialize/helper.hpp | 62 ++++++++++++++++++++++++++ serialize/vector.hpp | 41 +++++++++++++++++ 14 files changed, 232 insertions(+), 204 deletions(-) delete mode 100644 anim/CMakeLists.txt delete mode 100644 anim/serialize.cpp delete mode 100644 anim/serialize.hpp delete mode 100644 json-magnum.hpp create mode 100644 serialize/CMakeLists.txt create mode 100644 serialize/anim.cpp create mode 100644 serialize/anim.hpp create mode 100644 serialize/helper.hpp create mode 100644 serialize/vector.hpp 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 #include +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 #include -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 #include #include @@ -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 parse_cmdline(int argc, const char* opts.width = w; if (int h = args.value("height"); h != 0) opts.height = h; + opts.output_dir = args.value("output"); opts.input_file = args.value("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/anim/serialize.cpp b/anim/serialize.cpp deleted file mode 100644 index 8c027d9c..00000000 --- a/anim/serialize.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "serialize.hpp" - -#include -#include - -#include "json-magnum.hpp" - -using Corrade::Utility::Error; - -#if defined __clang__ || defined __CLION_IDE__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wweak-vtables" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -#endif - -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim_frame, ground, offset, size) -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim_group, name, frames, ground) -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim, name, nframes, actionframe, fps, groups, width, height) - -#if defined __clang__ || defined __CLION_IDE__ -# pragma clang diagnostic pop -#endif - -std::tuple anim::from_json(const std::filesystem::path& pathname) noexcept -{ - return json_helper::from_json(pathname); -} - -bool anim::to_json(const std::filesystem::path& pathname) const noexcept -{ - return json_helper::to_json(*this, pathname); -} diff --git a/anim/serialize.hpp b/anim/serialize.hpp deleted file mode 100644 index 3e039a96..00000000 --- a/anim/serialize.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include - -namespace std::filesystem { class path; } - -struct anim_frame final -{ - Magnum::Vector2i ground, offset, size; -}; - -enum class anim_direction : unsigned char -{ - N, NE, E, SE, S, SW, W, NW, - COUNT, -}; - -struct anim_group final -{ - std::string name; - std::vector frames; - Magnum::Vector2i ground; -}; - -struct anim final -{ - static std::tuple from_json(const std::filesystem::path& pathname) noexcept; - [[nodiscard]] bool to_json(const std::filesystem::path& pathname) const noexcept; - static constexpr int default_fps = 24; - - std::string name; - std::array groups; - int nframes = 0; - int width = 0, height = 0; - int actionframe = -1, fps = default_fps; -}; diff --git a/json-magnum.hpp b/json-magnum.hpp deleted file mode 100644 index bcd17e0a..00000000 --- a/json-magnum.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nlohmann { - -template<> -struct adl_serializer final { - static void to_json(json& j, const Magnum::Vector2i& x); - static void from_json(const json& j, Magnum::Vector2i& x); -}; - -void adl_serializer::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::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 -struct json_helper final { - [[nodiscard]] static std::tuple from_json(const std::filesystem::path& pathname) noexcept; - [[nodiscard]] static bool to_json(const t& self, const std::filesystem::path& pathname) noexcept; -}; - -template -std::tuple json_helper::from_json(const std::filesystem::path& pathname) noexcept { - using namespace nlohmann; - using Corrade::Utility::Error; - std::ifstream s; - s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); - try { - s.open(pathname, std::ios_base::in); - } catch (const std::ios::failure& e) { - Error{Error::Flag::NoSpace} << "failed to open " << pathname << ": " << e.what(); - return { {}, false }; - } - t ret; - try { - json j; - s >> j; - using nlohmann::from_json; - from_json(j, ret); - } catch (const std::exception& e) { - Error{Error::Flag::NoSpace} << "failed to parse " << pathname << ": " << e.what(); - return { {}, false }; - } - return { std::move(ret), true }; -} - -template -bool json_helper::to_json(const t& self, const std::filesystem::path& pathname) noexcept { - using Corrade::Utility::Error; - try { - nlohmann::json j = self; - - std::ofstream s; - s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); - 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(); - return false; - } - s << j.dump(4); - s.flush(); - } catch (const std::exception& e) { - Error{Error::Flag::NoSpace} << "failed writing to " << pathname << ": " << e.what(); - return false; - } - - return true; -} 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/serialize/anim.cpp b/serialize/anim.cpp new file mode 100644 index 00000000..c65c24a6 --- /dev/null +++ b/serialize/anim.cpp @@ -0,0 +1,36 @@ +#include "serialize/vector.hpp" +#include "serialize/helper.hpp" +#include "serialize/anim.hpp" + +#include +#include +#include +#include + +namespace Magnum::Examples::Serialize { + +#if defined __clang__ || defined __CLION_IDE__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wweak-vtables" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +#endif + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim_frame, ground, offset, size) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim_group, name, frames, ground) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(anim, name, nframes, actionframe, fps, groups, width, height) + +#if defined __clang__ || defined __CLION_IDE__ +# pragma clang diagnostic pop +#endif + +std::tuple anim::from_json(const std::filesystem::path& pathname) noexcept +{ + return json_helper::from_json(pathname); +} + +bool anim::to_json(const std::filesystem::path& pathname) const noexcept +{ + return json_helper::to_json(*this, pathname); +} + +} // namespace Magnum::Examples::Serialize diff --git a/serialize/anim.hpp b/serialize/anim.hpp new file mode 100644 index 00000000..f03e3c8c --- /dev/null +++ b/serialize/anim.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace std::filesystem { class path; } + +namespace Magnum::Examples::Serialize { + +struct anim_frame final +{ + Magnum::Vector2i ground, offset, size; +}; + +enum class anim_direction : unsigned char +{ + N, NE, E, SE, S, SW, W, NW, + COUNT, +}; + +struct anim_group final +{ + std::string name; + std::vector frames; + Magnum::Vector2i ground; +}; + +struct anim final +{ + static std::tuple from_json(const std::filesystem::path& pathname) noexcept; + [[nodiscard]] bool to_json(const std::filesystem::path& pathname) const noexcept; + static constexpr int default_fps = 24; + + std::string name; + std::array groups; + int nframes = 0; + int width = 0, height = 0; + int actionframe = -1, fps = default_fps; +}; + +} // namespace Magnum::Examples::Serialize + diff --git a/serialize/helper.hpp b/serialize/helper.hpp new file mode 100644 index 00000000..f16ed60c --- /dev/null +++ b/serialize/helper.hpp @@ -0,0 +1,62 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +template +struct json_helper final { + [[nodiscard]] static std::tuple from_json(const std::filesystem::path& pathname) noexcept; + [[nodiscard]] static bool to_json(const t& self, const std::filesystem::path& pathname) noexcept; +}; + +template +std::tuple json_helper::from_json(const std::filesystem::path& pathname) noexcept { + using namespace nlohmann; + using Corrade::Utility::Error; + std::ifstream s; + s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); + try { + s.open(pathname, std::ios_base::in); + } catch (const std::ios::failure& e) { + Error{Error::Flag::NoSpace} << "failed to open '" << pathname << "': " << e.what(); + return { {}, false }; + } + t ret; + try { + json j; + s >> j; + using nlohmann::from_json; + from_json(j, ret); + } catch (const std::exception& e) { + Error{Error::Flag::NoSpace} << "failed to parse '" << pathname << "': " << e.what(); + return { {}, false }; + } + return { std::move(ret), true }; +} + +template +bool json_helper::to_json(const t& self, const std::filesystem::path& pathname) noexcept { + using Corrade::Utility::Error; + try { + nlohmann::json j = self; + + std::ofstream s; + s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); + try { + s.open(pathname, std::ios_base::out | std::ios_base::trunc); + } catch (const std::ios::failure& e) { + 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(); + return false; + } + + return true; +} 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 +#include +#include +#include +#include +#include + +namespace nlohmann { + +template +struct adl_serializer> final { + static void to_json(json& j, const Magnum::Math::Vector2& x); + static void from_json(const json& j, Magnum::Math::Vector2& x); +}; + +template +void adl_serializer>::to_json(json& j, const Magnum::Math::Vector2& val) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%d x %d", val[0], val[1]); + j = buf; +} + +template +void adl_serializer>::from_json(const json& j, Magnum::Math::Vector2& 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 -- cgit v1.2.3