diff options
-rw-r--r-- | anim-crop-tool/main.cpp | 46 | ||||
-rw-r--r-- | floormat/main.hpp | 4 | ||||
-rw-r--r-- | loader/atlas.cpp | 4 | ||||
-rw-r--r-- | loader/vobj.cpp | 20 | ||||
-rw-r--r-- | main/main-impl.cpp | 3 | ||||
-rw-r--r-- | main/main-impl.hpp | 8 | ||||
-rw-r--r-- | serialize/anim.cpp | 6 | ||||
-rw-r--r-- | serialize/corrade-array.hpp | 28 | ||||
-rw-r--r-- | serialize/world-reader.cpp | 1 | ||||
-rw-r--r-- | src/anim-atlas.cpp | 2 | ||||
-rw-r--r-- | src/anim.hpp | 6 | ||||
-rw-r--r-- | src/path-search.hpp | 3 |
12 files changed, 93 insertions, 38 deletions
diff --git a/anim-crop-tool/main.cpp b/anim-crop-tool/main.cpp index 3f314719..5c96de62 100644 --- a/anim-crop-tool/main.cpp +++ b/anim-crop-tool/main.cpp @@ -9,12 +9,10 @@ #include "serialize/json-helper.hpp" #include "serialize/anim.hpp" -#include <cerrno> -#include <cmath> -#include <cstring> -#include <algorithm> #include <tuple> +#include <algorithm> +#include <Corrade/Containers/GrowableArray.h> #include <Corrade/Containers/Pair.h> #include <Corrade/Containers/StringView.h> #include <Corrade/Containers/String.h> @@ -24,6 +22,8 @@ #include <Corrade/Utility/Move.h> #include <Corrade/Utility/Path.h> +#include <Magnum/Math/Functions.h> + #include <opencv2/core/mat.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/imgcodecs/imgcodecs.hpp> @@ -43,8 +43,14 @@ struct options anim_scale scale; }; +struct image_bounds_tuple +{ + cv::Vec2i start, end; + bool ret; +}; + [[nodiscard]] -std::tuple<cv::Vec2i, cv::Vec2i, bool> find_image_bounds(const cv::Mat4b& mat) noexcept +image_bounds_tuple find_image_bounds(const cv::Mat4b& mat) noexcept { cv::Vec2i start{mat.cols, mat.rows}, end{0, 0}; for (int y = 0; y < mat.rows; y++) @@ -55,10 +61,10 @@ std::tuple<cv::Vec2i, cv::Vec2i, bool> find_image_bounds(const cv::Mat4b& mat) n enum {R, G, B, A}; if (cv::Vec4b px = ptr[x]; px[A] != 0) { - start[0] = std::min(x, start[0]); - start[1] = std::min(y, start[1]); - end[0] = std::max(x+1, end[0]); - end[1] = std::max(y+1, end[1]); + start[0] = Math::min(x, start[0]); + start[1] = Math::min(y, start[1]); + end[0] = Math::max(x+1, end[0]); + end[1] = Math::max(y+1, end[1]); } } } @@ -117,13 +123,13 @@ bool load_file(anim_group& group, options& opts, anim_atlas_& atlas, StringView cv::resize(mat({start, size}), resized, dest_size, 0, 0, cv::INTER_LANCZOS4); const Vector2i ground = { - (int)std::round(((int)group.ground[0] - start[0]) * factor), - (int)std::round(((int)group.ground[1] - start[1]) * factor), + (int)Math::round(((int)group.ground[0] - start[0]) * factor), + (int)Math::round(((int)group.ground[1] - start[1]) * factor), }; const Vector2ui dest_size_ = { (unsigned)dest_size.width, (unsigned)dest_size.height }; - group.frames.push_back({ground, atlas.offset(), dest_size_}); + arrayAppend(group.frames, {ground, atlas.offset(), dest_size_}); atlas.add_entry({&group.frames.back(), Utility::move(resized)}); return true; } @@ -166,11 +172,10 @@ bool load_directory(anim_group& group, options& opts, anim_atlas_& atlas) return false; } - group.frames.clear(); + arrayReserve(group.frames, (size_t)max-1); + arrayResize(group.frames, 0); // atlas stores its entries through a pointer. - // vector::reserve() is necessary to avoid use-after-free. - group.frames.reserve((size_t)max-1); - + // arrayReserve() is necessary to avoid use-after-free. for (unsigned i = 1; i < max; i++) { char filename[9]; @@ -196,7 +201,14 @@ inline String fixsep(String str) using Corrade::Utility::Arguments; -std::tuple<options, Arguments, bool> parse_cmdline(int argc, const char* const* argv) noexcept +struct arg_tuple +{ + options opts; + Arguments args; + bool ret; +}; + +arg_tuple parse_cmdline(int argc, const char* const* argv) noexcept { Corrade::Utility::Arguments args{}; args.addOption('o', "output").setHelp("output", "", "DIR") diff --git a/floormat/main.hpp b/floormat/main.hpp index cfb41f1d..a6f67ab0 100644 --- a/floormat/main.hpp +++ b/floormat/main.hpp @@ -23,7 +23,7 @@ struct wall_mesh; struct anim_mesh; struct texture_unit_cache; class path_search; -struct astar; +class astar; struct floormat_main { @@ -82,7 +82,7 @@ struct floormat_main virtual struct texture_unit_cache& texture_unit_cache() = 0; virtual path_search& search() = 0; - virtual struct astar& astar() = 0; + virtual class astar& astar() = 0; [[nodiscard]] static floormat_main* create(floormat_app& app, fm_settings&& options); [[maybe_unused]] static void debug_break(); diff --git a/loader/atlas.cpp b/loader/atlas.cpp index f61502fe..100f638e 100644 --- a/loader/atlas.cpp +++ b/loader/atlas.cpp @@ -75,7 +75,7 @@ std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name, StringView [&](const anim_group& x) { return x.name == group.mirror_from; }); if (it == anim_info.groups.cend()) fm_throw("can't find group '{}' to mirror from '{}'"_cf, group.mirror_from, group.name); - group.frames = it->frames; + group.frames = array(arrayView(it->frames)); for (anim_frame& f : group.frames) f.ground = Vector2i((Int)f.size[0] - f.ground[0], f.ground[1]); } @@ -85,7 +85,7 @@ std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name, StringView fm_soft_assert(!anim_info.object_name.isEmpty()); fm_soft_assert(anim_info.pixel_size.product() > 0); - fm_soft_assert(!anim_info.groups.empty()); + fm_soft_assert(!anim_info.groups.isEmpty()); fm_soft_assert(anim_info.nframes > 0); fm_soft_assert(anim_info.nframes == 1 || anim_info.fps > 0); const auto size = tex.pixels().size(); diff --git a/loader/vobj.cpp b/loader/vobj.cpp index 637ba776..5f7fc2fe 100644 --- a/loader/vobj.cpp +++ b/loader/vobj.cpp @@ -57,13 +57,19 @@ std::shared_ptr<class anim_atlas> loader_impl::make_vobj_anim_atlas(StringView n def.pixel_size = { width, height }; def.nframes = 1; def.fps = 0; - def.groups = {{ - .name = "n"_s, - .frames = {{ - .ground = Vector2i(def.pixel_size/2), - .size = def.pixel_size - }} - }}; + { + auto group = anim_group { + .name = "n"_s, + .frames = { InPlaceInit, { + anim_frame { + .ground = Vector2i(def.pixel_size/2), + .size = def.pixel_size, + }}, + }, + }; + def.groups = Array<anim_group>{1}; + def.groups[0] = std::move(group); + } auto atlas = std::make_shared<class anim_atlas>(name, tex, std::move(def)); return atlas; } diff --git a/main/main-impl.cpp b/main/main-impl.cpp index cb74de85..6875f751 100644 --- a/main/main-impl.cpp +++ b/main/main-impl.cpp @@ -1,4 +1,5 @@ #include "main-impl.hpp" +#include "src/path-search.hpp" #include <Corrade/Utility/Move.h> #include <Magnum/Platform/Sdl2Application.h> @@ -63,7 +64,7 @@ uint32_t main_impl::cursor() const noexcept } struct texture_unit_cache& main_impl::texture_unit_cache() { return _tuc; } -path_search& main_impl::search() { return _search; } +path_search& main_impl::search() { return *_search; } astar& main_impl::astar() { return _astar; } } // namespace floormat diff --git a/main/main-impl.hpp b/main/main-impl.hpp index b6d1b1f4..522183e6 100644 --- a/main/main-impl.hpp +++ b/main/main-impl.hpp @@ -31,6 +31,8 @@ struct floormat_app; struct scenery; class anim_atlas; struct clickable; +class path_search; +class astar; struct main_impl final : Platform::Sdl2Application, floormat_main { @@ -98,7 +100,7 @@ struct main_impl final : Platform::Sdl2Application, floormat_main struct texture_unit_cache& texture_unit_cache() override; path_search& search() override; - struct astar& astar() override; + class astar& astar() override; private: struct texture_unit_cache _tuc; @@ -117,8 +119,8 @@ private: #ifdef FM_USE_DEPTH32 Framebuffer framebuffer; #endif - path_search _search; - struct astar _astar; + safe_ptr<path_search> _search; + class astar _astar; struct { float value = 0; diff --git a/serialize/anim.cpp b/serialize/anim.cpp index 443fc34b..4b5dee77 100644 --- a/serialize/anim.cpp +++ b/serialize/anim.cpp @@ -1,7 +1,10 @@ #include "serialize/magnum-vector.hpp" #include "serialize/corrade-string.hpp" #include "serialize/anim.hpp" +#include "serialize/corrade-array.hpp" #include "compat/exception.hpp" +#include <Corrade/Containers/Array.h> +#include <Corrade/Containers/ArrayViewStl.h> #include <nlohmann/json.hpp> #include <tuple> @@ -115,8 +118,9 @@ static void from_json(const json& j, anim_def& val) val.action_frame2 = j["action-frame-2"]; if (j.contains("fps")) val.fps = j["fps"]; + val.groups = j["groups"]; - fm_soft_assert(!val.groups.empty()); + fm_soft_assert(!val.groups.isEmpty()); val.scale = j["scale"]; fm_soft_assert(val.scale.type != anim_scale_type::invalid); } diff --git a/serialize/corrade-array.hpp b/serialize/corrade-array.hpp new file mode 100644 index 00000000..ea450870 --- /dev/null +++ b/serialize/corrade-array.hpp @@ -0,0 +1,28 @@ +#pragma once +#include "compat/exception.hpp" +#include <Corrade/Containers/Array.h> +#include <nlohmann/json.hpp> + +namespace nlohmann { + +template<typename T, typename D> +struct adl_serializer<Corrade::Containers::Array<T, D>> +{ + static void to_json(json& j, const Corrade::Containers::Array<T, D>& array) + { + j.clear(); + for (const T& x : array) + j.push_back(x); + } + + static void from_json(const json& j, Corrade::Containers::Array<T>& array) + { + fm_soft_assert(j.is_array()); + auto size = (uint32_t)j.size(); + array = Corrade::Containers::Array<T>{size}; + for (uint32_t i = 0; i < size; i++) + array[i] = j[i]; + } +}; + +} // namespace nlohmann diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp index 6bfcaa47..366648d5 100644 --- a/serialize/world-reader.cpp +++ b/serialize/world-reader.cpp @@ -14,6 +14,7 @@ #include <cerrno> #include <cstring> #include <memory> +#include <vector> namespace { diff --git a/src/anim-atlas.cpp b/src/anim-atlas.cpp index c6a7c2f2..353ebb34 100644 --- a/src/anim-atlas.cpp +++ b/src/anim-atlas.cpp @@ -40,7 +40,7 @@ anim_atlas::anim_atlas(String name, const ImageView2D& image, anim_def info) : _name{std::move(name)}, _bitmask{make_bitmask(image)}, _info{std::move(info)}, _group_indices{make_group_indices(_info)} { - fm_soft_assert(!_info.groups.empty()); + fm_soft_assert(!_info.groups.isEmpty()); const Size<3> size = image.pixels().size(); fm_soft_assert(size[0]*size[1] == _info.pixel_size.product()); diff --git a/src/anim.hpp b/src/anim.hpp index 3b4d70a9..3c25f51c 100644 --- a/src/anim.hpp +++ b/src/anim.hpp @@ -1,6 +1,6 @@ #pragma once -#include <vector> // todo use <Corrade/Containers/GrowableArray.h> +#include <Corrade/Containers/Array.h> #include <Corrade/Containers/String.h> #include <Magnum/Magnum.h> #include <Magnum/Math/Vector2.h> @@ -23,7 +23,7 @@ enum class anim_direction : unsigned char struct anim_group final { String name{}, mirror_from{}; - std::vector<anim_frame> frames{}; + Array<anim_frame> frames{}; Vector2ui ground{}; // for use in anim-crop-tool only Vector2s z_offset{}, depth_offset{}; Vector3b offset{}; @@ -54,7 +54,7 @@ struct anim_scale final struct anim_def final { String object_name{}, anim_name{}; - std::vector<anim_group> groups{}; + Array<anim_group> groups{}; Vector2ui pixel_size{}; anim_scale scale = anim_scale::ratio{1}; size_t nframes = 0, fps = 0, action_frame = 0, action_frame2 = 0; diff --git a/src/path-search.hpp b/src/path-search.hpp index 8e56f4fd..512a507f 100644 --- a/src/path-search.hpp +++ b/src/path-search.hpp @@ -65,8 +65,9 @@ public: static bool is_passable(world& w, chunk_coords_ ch0, const bbox<float>& bb, object_id own_id, const pred& p = never_continue()); }; -struct astar +class astar { +public: struct visited { uint32_t dist = (uint32_t)-1; |