diff options
Diffstat (limited to 'loader')
-rw-r--r-- | loader/anim-cell.hpp (renamed from loader/anim-info.hpp) | 2 | ||||
-rw-r--r-- | loader/anim.cpp | 11 | ||||
-rw-r--r-- | loader/atlas-loader-fwd.hpp | 9 | ||||
-rw-r--r-- | loader/atlas-loader-storage.hpp | 23 | ||||
-rw-r--r-- | loader/atlas-loader.hpp | 32 | ||||
-rw-r--r-- | loader/atlas-loader.inl | 120 | ||||
-rw-r--r-- | loader/atlas.cpp | 5 | ||||
-rw-r--r-- | loader/error-tex.cpp | 2 | ||||
-rw-r--r-- | loader/ground-atlas.cpp | 146 | ||||
-rw-r--r-- | loader/ground-atlas.hpp | 7 | ||||
-rw-r--r-- | loader/ground-cell.hpp (renamed from loader/ground-info.hpp) | 8 | ||||
-rw-r--r-- | loader/ground-traits.cpp | 87 | ||||
-rw-r--r-- | loader/ground-traits.hpp | 25 | ||||
-rw-r--r-- | loader/impl.cpp | 38 | ||||
-rw-r--r-- | loader/impl.hpp | 34 | ||||
-rw-r--r-- | loader/json.cpp | 4 | ||||
-rw-r--r-- | loader/loader.cpp | 32 | ||||
-rw-r--r-- | loader/loader.hpp | 34 | ||||
-rw-r--r-- | loader/texture.cpp | 6 | ||||
-rw-r--r-- | loader/wall-atlas.cpp | 21 | ||||
-rw-r--r-- | loader/wall-cell.hpp (renamed from loader/wall-info.hpp) | 2 |
21 files changed, 426 insertions, 222 deletions
diff --git a/loader/anim-info.hpp b/loader/anim-cell.hpp index 97ba5954..a9c92a23 100644 --- a/loader/anim-info.hpp +++ b/loader/anim-cell.hpp @@ -6,7 +6,7 @@ namespace floormat { class anim_atlas; -struct anim_info +struct anim_cell { String name; std::shared_ptr<anim_atlas> atlas; diff --git a/loader/anim.cpp b/loader/anim.cpp index 25b5e292..6fca5a49 100644 --- a/loader/anim.cpp +++ b/loader/anim.cpp @@ -1,5 +1,5 @@ #include "impl.hpp" -#include "loader/anim-info.hpp" +#include "loader/anim-cell.hpp" #include "compat/exception.hpp" #include "src/anim-atlas.hpp" #include <Corrade/Containers/Array.h> @@ -58,9 +58,10 @@ ArrayView<const String> loader_impl::anim_atlas_list() std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name, StringView dir, loader_policy policy) noexcept(false) { if (name == INVALID) return make_invalid_anim_atlas().atlas; // todo! hack + fm_soft_assert(check_atlas_name(name)); fm_soft_assert(!dir || dir[dir.size()-1] == '/'); - char buf[FILENAME_MAX]; + char buf[fm_FILENAME_MAX]; auto path = make_atlas_path(buf, dir, name); if (auto it = anim_atlas_map.find(path); it != anim_atlas_map.end()) @@ -89,7 +90,7 @@ void loader_impl::get_anim_atlas_list() fm_assert(!anim_atlases.empty()); } -const anim_info& loader_impl::make_invalid_anim_atlas() +const anim_cell& loader_impl::make_invalid_anim_atlas() { if (invalid_anim_atlas) [[likely]] return *invalid_anim_atlas; @@ -115,11 +116,11 @@ const anim_info& loader_impl::make_invalid_anim_atlas() .nframes = 1, }; auto atlas = std::make_shared<class anim_atlas>(INVALID, make_error_texture(size), std::move(def)); - auto info = anim_info { + auto info = anim_cell{ .name = INVALID, .atlas = atlas, }; - invalid_anim_atlas = Pointer<anim_info>{ InPlace, std::move(info) }; + invalid_anim_atlas = Pointer<anim_cell>{ InPlace, std::move(info) }; return *invalid_anim_atlas; } diff --git a/loader/atlas-loader-fwd.hpp b/loader/atlas-loader-fwd.hpp new file mode 100644 index 00000000..2fe1cd84 --- /dev/null +++ b/loader/atlas-loader-fwd.hpp @@ -0,0 +1,9 @@ +#pragma once + +namespace floormat::loader_detail { + +template<typename ATLAS> struct atlas_loader_traits; +template<typename ATLAS, typename TRAITS = atlas_loader_traits<ATLAS>> class atlas_loader; +template<typename ATLAS, typename TRAITS = atlas_loader_traits<ATLAS>> struct atlas_storage; + +} // namespace floormat::loader_detail diff --git a/loader/atlas-loader-storage.hpp b/loader/atlas-loader-storage.hpp new file mode 100644 index 00000000..f428be0a --- /dev/null +++ b/loader/atlas-loader-storage.hpp @@ -0,0 +1,23 @@ +#pragma once +#include "compat/int-hash.hpp" +#include "atlas-loader-fwd.hpp" +#include <vector> +#include <tsl/robin_map.h> + +namespace floormat::loader_detail { + +template<typename ATLAS, typename TRAITS> +struct atlas_storage +{ + using Traits = TRAITS; + using Cell = typename TRAITS::Cell; + + tsl::robin_map<StringView, Cell*, hash_string_view> name_map; + std::vector<Cell> cell_array; + std::vector<String> missing_atlas_names; + Pointer<Cell> invalid_atlas; + + bool is_empty() const { return cell_array.empty(); } +}; + +} // namespace floormat::loader_detail diff --git a/loader/atlas-loader.hpp b/loader/atlas-loader.hpp new file mode 100644 index 00000000..9fa82e49 --- /dev/null +++ b/loader/atlas-loader.hpp @@ -0,0 +1,32 @@ +#pragma once +#include "compat/defs.hpp" +#include "atlas-loader-fwd.hpp" +#include "policy.hpp" +#include <memory> + +namespace floormat::loader_detail { + +template<typename ATLAS, typename TRAITS> +class atlas_loader final +{ + [[fm_no_unique_address]] TRAITS t; + atlas_storage<ATLAS, TRAITS> s; + +public: + using Traits = TRAITS; + using Atlas = ATLAS; + using Cell = typename TRAITS::Cell; + + ~atlas_loader() noexcept = default; + fm_DECLARE_DELETED_COPY_ASSIGNMENT(atlas_loader); + fm_DECLARE_DELETED_MOVE_ASSIGNMENT(atlas_loader); + + atlas_loader(TRAITS&& traits); + atlas_loader() requires std::is_default_constructible_v<TRAITS>; + + ArrayView<const Cell> ensure_atlas_list(); + const std::shared_ptr<Atlas>& get_atlas(StringView name, loader_policy p); + const Cell& get_invalid_atlas(); +}; + +} // namespace floormat::loader_detail diff --git a/loader/atlas-loader.inl b/loader/atlas-loader.inl new file mode 100644 index 00000000..a2e3e2a7 --- /dev/null +++ b/loader/atlas-loader.inl @@ -0,0 +1,120 @@ +#pragma once +#include "compat/assert.hpp" +#include "compat/exception.hpp" +#include "atlas-loader.hpp" +#include "atlas-loader-storage.hpp" +#include "loader/loader.hpp" + +namespace floormat::loader_detail { + +template<typename ATLAS, typename TRAITS> +atlas_loader<ATLAS, TRAITS>::atlas_loader(TRAITS&& traits): // NOLINT(*-rvalue-reference-param-not-moved) + t{Utility::move(traits)} +{} + +template<typename ATLAS, typename TRAITS> +atlas_loader<ATLAS, TRAITS>::atlas_loader() requires std::is_default_constructible_v<TRAITS>: atlas_loader{TRAITS{}} {} + +template<typename TRAITS> +atlas_loader(TRAITS&& traits) noexcept -> atlas_loader<TRAITS, typename TRAITS::Atlas>; + +template<typename ATLAS, typename TRAITS> +auto atlas_loader<ATLAS, TRAITS>::ensure_atlas_list() -> ArrayView<const Cell> +{ + if (!s.cell_array.empty()) [[likely]] + return { s.cell_array.data(), s.cell_array.size() }; + t.ensure_atlases_loaded(s); + fm_assert(!s.cell_array.empty()); + return { s.cell_array.data(), s.cell_array.size() }; +} + +template<typename ATLAS, typename TRAITS> +const std::shared_ptr<ATLAS>& atlas_loader<ATLAS, TRAITS>::get_atlas(StringView name, loader_policy p) +{ + ensure_atlas_list(); + auto* const invalid_atlas = const_cast<Cell*>(&t.make_invalid_atlas(s)); + fm_debug_assert(invalid_atlas); + fm_debug_assert(t.atlas_of(*invalid_atlas)); + + switch (p) + { + using enum loader_policy; + case error: + case ignore: + case warn: + break; + default: + fm_abort("invalid loader_policy (%d)", (int)p); + } + + if (name == loader.INVALID) [[unlikely]] + switch (p) + { + using enum loader_policy; + case error: + goto error; + case ignore: + case warn: + return invalid_atlas->atlas; + } + + fm_soft_assert(loader.check_atlas_name(name)); + + if (auto it = s.name_map.find(name); it != s.name_map.end()) [[likely]] + { + if (it->second == invalid_atlas) + { + switch (p) + { + using enum loader_policy; + case error: + goto error; + case warn: + case ignore: + return invalid_atlas->atlas; + } + } + else if (!it->second->atlas) + return it->second->atlas = t.make_atlas(name, *it->second); + else + return it->second->atlas; + } + else + switch (p) + { + using enum loader_policy; + case error: + goto error; + case warn: + goto missing_warn; + case ignore: + return invalid_atlas->atlas; + } + + std::unreachable(); + fm_assert(false); + +error: + fm_throw("no such atlas '{}'"_cf, name); + +missing_warn: + s.missing_atlas_names.push_back(String { AllocatedInit, name }); + s.name_map[ s.missing_atlas_names.back() ] = invalid_atlas; + + if (name != loader.INVALID) + { + DBG_nospace << t.loader_name() << " '" << name << "' doesn't exist"; + } + + return invalid_atlas->atlas; +} + +template<typename ATLAS, typename TRAITS> +auto atlas_loader<ATLAS, TRAITS>::get_invalid_atlas() -> const Cell& +{ + const auto& cell = t.make_invalid_atlas(s); + fm_assert(t.atlas_of(cell)); + return cell; +} + +} // namespace floormat::loader_detail diff --git a/loader/atlas.cpp b/loader/atlas.cpp index a4c38264..e856f639 100644 --- a/loader/atlas.cpp +++ b/loader/atlas.cpp @@ -1,6 +1,7 @@ #include "impl.hpp" //#include "compat/assert.hpp" #include "compat/exception.hpp" +#include "loader/loader.hpp" //#include "src/emplacer.hpp" //#include "src/anim-atlas.hpp" #include <cstring> @@ -13,11 +14,11 @@ namespace floormat { -StringView loader_::make_atlas_path(char(&buf)[FILENAME_MAX], StringView dir, StringView name) +StringView loader_::make_atlas_path(char(&buf)[fm_FILENAME_MAX], StringView dir, StringView name) { fm_soft_assert(!dir || dir[dir.size()-1] == '/'); const auto dirsiz = dir.size(), namesiz = name.size(); - fm_soft_assert(dirsiz + namesiz + 1 < FILENAME_MAX); + fm_soft_assert(dirsiz + namesiz + 1 < fm_FILENAME_MAX); std::memcpy(buf, dir.data(), dirsiz); std::memcpy(&buf[dirsiz], name.data(), namesiz); auto len = dirsiz + namesiz; diff --git a/loader/error-tex.cpp b/loader/error-tex.cpp index c3a0a58b..16df2b43 100644 --- a/loader/error-tex.cpp +++ b/loader/error-tex.cpp @@ -11,7 +11,7 @@ Trade::ImageData2D loader_impl::make_error_texture(Vector2ui size) { fm_assert(size.product() != 0); constexpr auto magenta = Vector4ub{255, 0, 255, 255}; - auto array = Array<char>{NoInit, 4 * size.product()}; + auto array = Array<char>{NoInit, 4uz * size.product()}; auto data = array.data(), end = data + array.size(); while (data != end) { diff --git a/loader/ground-atlas.cpp b/loader/ground-atlas.cpp index ba4eaeb0..02186cec 100644 --- a/loader/ground-atlas.cpp +++ b/loader/ground-atlas.cpp @@ -1,30 +1,36 @@ #include "impl.hpp" +#include "atlas-loader-storage.hpp" +#include "atlas-loader.inl" +#include "ground-traits.hpp" +#include "ground-cell.hpp" #include "src/tile-constants.hpp" #include "src/ground-atlas.hpp" #include "compat/exception.hpp" #include "serialize/json-helper.hpp" -#include "serialize/corrade-string.hpp" #include "serialize/ground-atlas.hpp" -#include "src/tile-defs.hpp" #include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Utility/Path.h> #include <Magnum/Trade/ImageData.h> #include <Magnum/ImageView.h> +namespace floormat::loader_detail { + +template class atlas_loader<ground_atlas>; + +} // namespace floormat::loader_detail + namespace floormat { -using loader_detail::loader_impl; + +using loader_detail::atlas_loader_traits; +using ALT = atlas_loader_traits<ground_atlas>; std::shared_ptr<ground_atlas> loader_::get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false) { fm_assert(name != loader.INVALID); - - char buf[FILENAME_MAX]; - auto filename = make_atlas_path(buf, loader.GROUND_TILESET_PATH, name); - auto tex = texture(""_s, filename); - + auto tex = texture(loader.GROUND_TILESET_PATH, name); auto info = ground_def{name, size, pass}; - auto atlas = std::make_shared<class ground_atlas>(info, filename, tex); + auto atlas = std::make_shared<class ground_atlas>(info, tex); return atlas; } @@ -32,128 +38,22 @@ loader_::get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexc namespace floormat::loader_detail { -// todo copypasta from wall-atlas.cpp -std::shared_ptr<class ground_atlas> loader_impl::ground_atlas(StringView name, loader_policy policy) noexcept(false) +atlas_loader<class ground_atlas>* loader_impl::make_ground_atlas_loader() { - (void)ground_atlas_list(); - - switch (policy) - { - case loader_policy::error: - fm_assert(name != INVALID); - break; - case loader_policy::ignore: - case loader_policy::warn: - break; - default: - fm_abort("invalid loader_policy"); - } - - fm_soft_assert(check_atlas_name(name)); - auto it = ground_atlas_map.find(name); - - if (it != ground_atlas_map.end()) [[likely]] - { - if (it->second == (ground_info*)-1) [[unlikely]] - { - switch (policy) - { - case loader_policy::error: - goto error; - case loader_policy::warn: - case loader_policy::ignore: - goto missing_ok; - } - fm_assert(false); - std::unreachable(); - } - else if (!it->second->atlas) - return it->second->atlas = get_ground_atlas(name, it->second->size, it->second->pass); - else - return it->second->atlas; - } - else - { - switch (policy) - { - case loader_policy::error: - goto error; - case loader_policy::warn: - goto missing_warn; - case loader_policy::ignore: - goto missing_ok; - } - fm_assert(false); - std::unreachable(); - } - -missing_warn: - { - missing_ground_atlases.push_back(String { AllocatedInit, name }); - auto string_view = StringView{missing_ground_atlases.back()}; - ground_atlas_map[string_view] = (ground_info*)-1; - } - - if (name != loader.INVALID) - DBG_nospace << "ground_atlas '" << name << "' doesn't exist"; - -missing_ok: - return make_invalid_ground_atlas().atlas; - -error: - fm_throw("no such ground atlas '{}'"_cf, name); + return new atlas_loader<class ground_atlas>; } -ArrayView<const ground_info> loader_impl::ground_atlas_list() noexcept(false) -{ - if (ground_atlas_map.empty()) [[unlikely]] - { - get_ground_atlas_list(); - fm_assert(!ground_atlas_map.empty()); - } - return ground_atlas_array; -} +auto loader_impl::ground_atlas_list() noexcept(false) -> ArrayView<const ground_cell> { return _ground_loader->ensure_atlas_list(); } -void loader_impl::get_ground_atlas_list() +const ground_cell& loader_impl::make_invalid_ground_atlas() { - fm_assert(ground_atlas_map.empty()); - - auto defs = json_helper::from_json<std::vector<ground_def>>(Path::join(loader_::GROUND_TILESET_PATH, "ground.json"_s)); - std::vector<ground_info> infos; - infos.reserve(defs.size()); - - for (auto& x : defs) - infos.push_back(ground_info{std::move(x.name), {}, x.size, x.pass}); - - ground_atlas_array = infos; - ground_atlas_array.shrink_to_fit(); - ground_atlas_map.clear(); - ground_atlas_map.reserve(ground_atlas_array.size()*2); - - for (auto& x : ground_atlas_array) - { - fm_soft_assert(x.name != loader.INVALID); - fm_soft_assert(check_atlas_name(x.name)); - StringView name = x.name; - ground_atlas_map[name] = &x; - fm_debug_assert(name.data() == ground_atlas_map[name]->name.data()); - } - - fm_assert(!ground_atlas_map.empty()); + return _ground_loader->get_invalid_atlas(); } -const ground_info& loader_impl::make_invalid_ground_atlas() +const std::shared_ptr<class ground_atlas>& +loader_impl::ground_atlas(StringView filename, loader_policy policy) noexcept(false) { - if (invalid_ground_atlas) [[likely]] - return *invalid_ground_atlas; - - auto atlas = std::make_shared<class ground_atlas>( - ground_def{loader.INVALID, Vector2ub{1,1}, pass_mode::pass}, - ""_s, make_error_texture(Vector2ui(iTILE_SIZE2))); - invalid_ground_atlas = Pointer<ground_info>{ - InPlaceInit, atlas->name(), - atlas, atlas->num_tiles2(), atlas->pass_mode()}; - return *invalid_ground_atlas; + return _ground_loader->get_atlas(filename, policy); } } // namespace floormat::loader_detail diff --git a/loader/ground-atlas.hpp b/loader/ground-atlas.hpp new file mode 100644 index 00000000..b388f543 --- /dev/null +++ b/loader/ground-atlas.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace floormat::loader_detail { + + + +} // namespace floormat::loader_detail diff --git a/loader/ground-info.hpp b/loader/ground-cell.hpp index 1a21e960..260301c2 100644 --- a/loader/ground-info.hpp +++ b/loader/ground-cell.hpp @@ -1,17 +1,15 @@ #pragma once -#include "src/pass-mode.hpp" +#include "src/ground-def.hpp" #include <memory> -#include <Corrade/Containers/String.h> -#include <Magnum/Math/Vector2.h> namespace floormat { class ground_atlas; -struct ground_info +struct ground_cell { - String name; std::shared_ptr<ground_atlas> atlas; + String name; Vector2ub size; pass_mode pass = pass_mode::pass; }; diff --git a/loader/ground-traits.cpp b/loader/ground-traits.cpp new file mode 100644 index 00000000..cf0dee4e --- /dev/null +++ b/loader/ground-traits.cpp @@ -0,0 +1,87 @@ +#include "ground-traits.hpp" +#include "compat/assert.hpp" +#include "compat/exception.hpp" +#include "atlas-loader.hpp" +#include "atlas-loader-storage.hpp" +#include "ground-cell.hpp" +#include "loader.hpp" +#include "src/tile-defs.hpp" +#include "serialize/json-helper.hpp" +#include "serialize/ground-atlas.hpp" +#include <Corrade/Containers/StringView.h> +#include <Corrade/Containers/Pointer.h> +#include <Corrade/Utility/Path.h> +#include <Magnum/ImageView.h> +#include <Magnum/Trade/ImageData.h> + +namespace floormat::loader_detail { + +StringView atlas_loader_traits<ground_atlas>::loader_name() { return "ground_atlas"_s; } +StringView atlas_loader_traits<ground_atlas>::name_of(const Cell& x) { return x.name; } +auto atlas_loader_traits<ground_atlas>::atlas_of(const Cell& x) -> const std::shared_ptr<Atlas>& { return x.atlas; } +StringView atlas_loader_traits<ground_atlas>::name_of(const Atlas& x) { return x.name(); } + +void atlas_loader_traits<ground_atlas>::ensure_atlases_loaded(Storage& st) +{ + if (!st.is_empty()) [[likely]] + return; + + fm_assert(st.cell_array.empty()); + fm_assert(st.name_map.empty()); + + auto defs = json_helper::from_json<std::vector<ground_def>>(Path::join(loader_::GROUND_TILESET_PATH, "ground.json"_s)); + std::vector<ground_cell> infos; + infos.reserve(defs.size()); + + for (auto& x : defs) + infos.push_back(ground_cell{{}, std::move(x.name), x.size, x.pass}); + + st.cell_array = Utility::move(infos); + fm_assert(!st.cell_array.empty()); + fm_assert(st.name_map.empty()); + + constexpr bool add_invalid = true; + + if constexpr(add_invalid) + for (auto& x : st.cell_array) + fm_soft_assert(x.name != loader.INVALID); + + if constexpr(true) // NOLINT(*-simplify-boolean-expr) + st.cell_array.push_back(make_invalid_atlas(st)); // add invalid atlas + + st.name_map.reserve(st.cell_array.size()); + + for (auto& x : st.cell_array) + { + if constexpr(!add_invalid) + fm_soft_assert(x.name != loader.INVALID); + fm_soft_assert(loader.check_atlas_name(x.name)); + st.name_map[x.name] = &x; + } + + fm_assert(!st.cell_array.empty()); + fm_assert(!st.name_map.empty()); + fm_debug_assert(!st.is_empty()); +} + +auto atlas_loader_traits<ground_atlas>::make_invalid_atlas(Storage& s) -> const Cell& +{ + if (!s.invalid_atlas) [[unlikely]] + { + auto atlas = std::make_shared<Atlas>( + ground_def{loader.INVALID, Vector2ub{1,1}, pass_mode::pass}, + loader.make_error_texture(Vector2ui(tile_size_xy))); + s.invalid_atlas = Pointer<ground_cell>{ InPlaceInit, atlas, atlas->name(), atlas->num_tiles2(), atlas->pass_mode() }; + } + return *s.invalid_atlas; +} + +auto atlas_loader_traits<ground_atlas>::make_atlas(StringView name, const Cell& cell) -> std::shared_ptr<Atlas> +{ + auto def = ground_def{name, cell.size, cell.pass}; + auto tex = loader.texture(loader.GROUND_TILESET_PATH, name); + auto atlas = std::make_shared<Atlas>(def, tex); + return atlas; +} + +} // namespace floormat::loader_detail diff --git a/loader/ground-traits.hpp b/loader/ground-traits.hpp new file mode 100644 index 00000000..56923cd0 --- /dev/null +++ b/loader/ground-traits.hpp @@ -0,0 +1,25 @@ +#pragma once +#include "atlas-loader-fwd.hpp" +#include <memory> + +namespace floormat { struct ground_cell; class ground_atlas; } + +namespace floormat::loader_detail { + +template<> struct atlas_loader_traits<ground_atlas> +{ + using Atlas = ground_atlas; + using Cell = ground_cell; // convertible to atlas and holding the atlas + using Self = atlas_loader_traits<ground_atlas>; + using Storage = atlas_storage<ground_atlas, Self>; + + static StringView loader_name(); + static const std::shared_ptr<Atlas>& atlas_of(const Cell& x); + static StringView name_of(const Cell& x); + static StringView name_of(const Atlas& x); + static void ensure_atlases_loaded(Storage& st); + static const Cell& make_invalid_atlas(Storage& st); + static std::shared_ptr<Atlas> make_atlas(StringView name, const Cell& c); +}; + +} // namespace floormat::loader_detail diff --git a/loader/impl.cpp b/loader/impl.cpp index 7da85f3f..543f0794 100644 --- a/loader/impl.cpp +++ b/loader/impl.cpp @@ -1,9 +1,13 @@ #include "impl.hpp" #include "compat/assert.hpp" -#include "loader/scenery.hpp" -#include "loader/wall-info.hpp" -#include "loader/anim-info.hpp" -#include "src/ground-atlas.hpp" +#include "scenery.hpp" +#include "wall-cell.hpp" +#include "anim-cell.hpp" +#include "ground-cell.hpp" +#include "ground-traits.hpp" +#include "atlas-loader.hpp" +#include "atlas-loader-storage.hpp" + #include <Corrade/Containers/Pair.h> #include <Magnum/Trade/ImageData.h> @@ -11,6 +15,10 @@ #pragma GCC diagnostic ignored "-Walloca" #endif +namespace floormat { + +} // namespace floormat + namespace floormat::loader_detail { StringView loader_impl::shader(StringView filename) noexcept @@ -23,9 +31,9 @@ StringView loader_impl::shader(StringView filename) noexcept return ret; } -loader_impl::loader_impl() +loader_impl::loader_impl() : + _ground_loader{ make_ground_atlas_loader() } { - missing_ground_atlases.reserve(32); missing_wall_atlases.reserve(32); system_init(); set_application_working_directory(); @@ -46,4 +54,22 @@ void loader_impl::ensure_plugins() fm_assert(tga_importer); } +void loader_impl::destroy() +{ + wall_atlas_map.clear(); + wall_atlas_array.clear(); + invalid_wall_atlas = nullptr; + missing_wall_atlases.clear(); + _ground_loader = {InPlace}; + anim_atlas_map.clear(); + anim_atlases.clear(); + invalid_anim_atlas = nullptr; + sceneries_map.clear(); + sceneries_array.clear(); + + vobj_atlas_map.clear(); + vobjs.clear(); +} + + } // namespace floormat::loader_detail diff --git a/loader/impl.hpp b/loader/impl.hpp index 5c8a542a..7bddda29 100644 --- a/loader/impl.hpp +++ b/loader/impl.hpp @@ -1,5 +1,7 @@ #pragma once +#include "compat/safe-ptr.hpp" #include "loader/loader.hpp" +#include "atlas-loader-fwd.hpp" #include <tsl/robin_map.h> #include <memory> #include <vector> @@ -12,6 +14,9 @@ namespace floormat::loader_detail { + + + struct loader_impl final : loader_ { explicit loader_impl(); @@ -36,37 +41,34 @@ struct loader_impl final : loader_ Optional<Utility::Resource> shader_res; StringView shader(StringView filename) noexcept override; - Trade::ImageData2D make_error_texture(Vector2ui size); + Trade::ImageData2D make_error_texture(Vector2ui size) override; Trade::ImageData2D texture(StringView prefix, StringView filename) noexcept(false) override; // >-----> walls >-----> - tsl::robin_map<StringView, wall_info*> wall_atlas_map; - std::vector<wall_info> wall_atlas_array; + tsl::robin_map<StringView, wall_cell*> wall_atlas_map; + std::vector<wall_cell> wall_atlas_array; std::vector<String> missing_wall_atlases; - Pointer<wall_info> invalid_wall_atlas; + Pointer<wall_cell> invalid_wall_atlas; std::shared_ptr<class wall_atlas> wall_atlas(StringView name, loader_policy policy) override; - ArrayView<const wall_info> wall_atlas_list() override; + ArrayView<const wall_cell> wall_atlas_list() override; void get_wall_atlas_list(); - const wall_info& make_invalid_wall_atlas() override; + const wall_cell& make_invalid_wall_atlas() override; // >-----> ground >-----> - tsl::robin_map<StringView, ground_info*> ground_atlas_map; - std::vector<ground_info> ground_atlas_array; - std::vector<String> missing_ground_atlases; - Pointer<ground_info> invalid_ground_atlas; - std::shared_ptr<class ground_atlas> ground_atlas(StringView filename, loader_policy policy) noexcept(false) override; - ArrayView<const ground_info> ground_atlas_list() noexcept(false) override; - void get_ground_atlas_list(); - const ground_info& make_invalid_ground_atlas() override; + static atlas_loader<class ground_atlas>* make_ground_atlas_loader(); + safe_ptr<atlas_loader<class ground_atlas>> _ground_loader{make_ground_atlas_loader()}; + const std::shared_ptr<class ground_atlas>& ground_atlas(StringView filename, loader_policy policy) noexcept(false) override; + ArrayView<const ground_cell> ground_atlas_list() noexcept(false) override; + const ground_cell& make_invalid_ground_atlas() override; // >-----> anim >-----> tsl::robin_map<StringView, std::shared_ptr<class anim_atlas>> anim_atlas_map; std::vector<String> anim_atlases; - Pointer<anim_info> invalid_anim_atlas; + Pointer<anim_cell> invalid_anim_atlas; ArrayView<const String> anim_atlas_list() override; std::shared_ptr<class anim_atlas> anim_atlas(StringView name, StringView dir, loader_policy policy) noexcept(false) override; void get_anim_atlas_list(); - const anim_info& make_invalid_anim_atlas() override; + const anim_cell& make_invalid_anim_atlas() override; // >-----> scenery >-----> std::vector<serialized_scenery> sceneries_array; diff --git a/loader/json.cpp b/loader/json.cpp index 5c7eecb5..d374571c 100644 --- a/loader/json.cpp +++ b/loader/json.cpp @@ -6,7 +6,7 @@ #include "serialize/anim.hpp" #include "serialize/scenery.hpp" #include "loader/scenery.hpp" -#include "loader/anim-info.hpp" +#include "loader/anim-cell.hpp" #include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Utility/Path.h> @@ -26,7 +26,7 @@ void loader_impl::get_scenery_list() sceneries_array.clear(); sceneries_array = json_helper::from_json<std::vector<serialized_scenery>>(Path::join(SCENERY_PATH, "scenery.json")); - if constexpr(false) + if constexpr(true) // todo! { auto proto = scenery_proto{}; proto.atlas = make_invalid_anim_atlas().atlas; diff --git a/loader/loader.cpp b/loader/loader.cpp index 531d731a..8b711206 100644 --- a/loader/loader.cpp +++ b/loader/loader.cpp @@ -1,35 +1,9 @@ #include "impl.hpp" -#include "ground-info.hpp" -#include "wall-info.hpp" -#include "anim-info.hpp" +#include "ground-cell.hpp" +#include "loader/wall-cell.hpp" +#include "anim-cell.hpp" #include "scenery.hpp" -namespace floormat::loader_detail { - -void loader_impl::destroy() -{ - wall_atlas_map.clear(); - wall_atlas_array.clear(); - invalid_wall_atlas = nullptr; - missing_wall_atlases.clear(); - - ground_atlas_map.clear(); - ground_atlas_array.clear(); - invalid_ground_atlas = nullptr; - missing_ground_atlases.clear(); - - anim_atlas_map.clear(); - anim_atlases.clear(); - invalid_anim_atlas = nullptr; - sceneries_map.clear(); - sceneries_array.clear(); - - vobj_atlas_map.clear(); - vobjs.clear(); -} - -} // namespace floormat::loader_detail - namespace floormat { using loader_detail::loader_impl; diff --git a/loader/loader.hpp b/loader/loader.hpp index 96ab57ed..faa0269a 100644 --- a/loader/loader.hpp +++ b/loader/loader.hpp @@ -2,27 +2,26 @@ #include "compat/defs.hpp" #include "src/pass-mode.hpp" #include "loader/policy.hpp" -#include <stdio.h> // NOLINT(*-deprecated-headers) #include <memory> #include <Corrade/Containers/String.h> -namespace Magnum { using Vector2ub = Math::Vector2<unsigned char>; } -namespace floormat { struct serialized_scenery; } -namespace Magnum::Trade { -template<uint32_t> class ImageData; -using ImageData2D = ImageData<2>; -} // namespace Magnum::Trade +//namespace Magnum { using Vector2ub = Math::Vector2<unsigned char>; } +namespace Magnum::Trade { template<uint32_t> class ImageData; using ImageData2D = ImageData<2>; } namespace floormat { +struct serialized_scenery; +namespace loader_detail {} +namespace Serialize {} + struct anim_def; class anim_atlas; -struct anim_info; +struct anim_cell; struct scenery_proto; struct vobj_info; class ground_atlas; -struct ground_info; -struct wall_info; +struct ground_cell; +struct wall_cell; class wall_atlas; struct scenery_proto; @@ -35,27 +34,28 @@ struct vobj_info final struct loader_ { virtual StringView shader(StringView filename) noexcept = 0; + virtual Trade::ImageData2D make_error_texture(Vector2ui size) = 0; virtual Trade::ImageData2D texture(StringView prefix, StringView filename) noexcept(false) = 0; - virtual std::shared_ptr<class ground_atlas> ground_atlas(StringView filename, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; + virtual const std::shared_ptr<class ground_atlas>& ground_atlas(StringView filename, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; virtual ArrayView<const String> anim_atlas_list() = 0; virtual std::shared_ptr<class anim_atlas> anim_atlas(StringView name, StringView dir = ANIM_PATH, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; virtual std::shared_ptr<class wall_atlas> wall_atlas(StringView name, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; - virtual ArrayView<const wall_info> wall_atlas_list() = 0; + virtual ArrayView<const wall_cell> wall_atlas_list() = 0; virtual void destroy() = 0; static loader_& default_loader() noexcept; - virtual ArrayView<const ground_info> ground_atlas_list() noexcept(false) = 0; // todo maybe try returning + virtual ArrayView<const ground_cell> ground_atlas_list() noexcept(false) = 0; // todo maybe try returning virtual ArrayView<const serialized_scenery> sceneries() = 0; virtual const scenery_proto& scenery(StringView name) noexcept(false) = 0; virtual StringView startup_directory() noexcept = 0; static StringView strip_prefix(StringView name); virtual const vobj_info& vobj(StringView name) = 0; virtual ArrayView<const struct vobj_info> vobj_list() = 0; - static StringView make_atlas_path(char(&buf)[FILENAME_MAX], StringView dir, StringView name); + static StringView make_atlas_path(char(&buf)[fm_FILENAME_MAX], StringView dir, StringView name); [[nodiscard]] static bool check_atlas_name(StringView name) noexcept; - virtual const wall_info& make_invalid_wall_atlas() = 0; - virtual const ground_info& make_invalid_ground_atlas() = 0; - virtual const anim_info& make_invalid_anim_atlas() = 0; + virtual const wall_cell& make_invalid_wall_atlas() = 0; + virtual const ground_cell& make_invalid_ground_atlas() = 0; + virtual const anim_cell& make_invalid_anim_atlas() = 0; /** \deprecated{internal use only}*/ [[nodiscard]] std::shared_ptr<class ground_atlas> get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false); diff --git a/loader/texture.cpp b/loader/texture.cpp index 8ac9e793..e93b21af 100644 --- a/loader/texture.cpp +++ b/loader/texture.cpp @@ -4,7 +4,7 @@ #include "compat/defs.hpp" #include "compat/strerror.hpp" #include <cstring> -#include <cstdio> +//#include <cstdio> #include <Corrade/Utility/Path.h> #include <Magnum/Trade/ImageData.h> @@ -19,11 +19,11 @@ Trade::ImageData2D loader_impl::texture(StringView prefix, StringView filename_) const auto N = prefix.size(); if (N > 0) [[likely]] fm_assert(prefix[N-1] == '/'); - fm_soft_assert(filename_.size() + prefix.size() + max_extension_length + 1 < FILENAME_MAX); + fm_soft_assert(filename_.size() + prefix.size() + max_extension_length + 1 < fm_FILENAME_MAX); fm_soft_assert(check_atlas_name(filename_)); fm_soft_assert(tga_importer); - char buf[FILENAME_MAX]; + char buf[fm_FILENAME_MAX]; const auto path_no_ext = make_atlas_path(buf, prefix, filename_); const auto len = path_no_ext.size(); diff --git a/loader/wall-atlas.cpp b/loader/wall-atlas.cpp index ee33e052..80eb6e0f 100644 --- a/loader/wall-atlas.cpp +++ b/loader/wall-atlas.cpp @@ -1,12 +1,11 @@ #include "loader/impl.hpp" #include "src/tile-constants.hpp" -#include "wall-info.hpp" +#include "loader/wall-cell.hpp" #include "compat/assert.hpp" #include "compat/exception.hpp" #include "src/wall-atlas.hpp" #include "serialize/json-helper.hpp" #include "serialize/corrade-string.hpp" -#include "src/tile-defs.hpp" #include <Corrade/Containers/Array.h> #include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Containers/StringIterable.h> @@ -19,14 +18,14 @@ namespace floormat { using nlohmann::json; using loader_detail::loader_impl; -[[maybe_unused]] static void from_json(const json& j, wall_info& val) +[[maybe_unused]] static void from_json(const json& j, wall_cell& val) { val = {}; val.name = j["name"]; fm_soft_assert(loader.check_atlas_name(val.name)); } -[[maybe_unused]] static void to_json(json& j, const wall_info& val) +[[maybe_unused]] static void to_json(json& j, const wall_cell& val) { j["name"] = val.name; } @@ -34,7 +33,7 @@ using loader_detail::loader_impl; std::shared_ptr<wall_atlas> loader_::get_wall_atlas(StringView name) noexcept(false) { fm_assert(name != "<invalid>"_s); - char buf[FILENAME_MAX]; + char buf[fm_FILENAME_MAX]; auto filename = make_atlas_path(buf, loader.WALL_TILESET_PATH, name); auto def = wall_atlas_def::deserialize(""_s.join({filename, ".json"_s})); auto tex = texture(""_s, filename); @@ -49,7 +48,7 @@ std::shared_ptr<wall_atlas> loader_::get_wall_atlas(StringView name) noexcept(fa namespace floormat::loader_detail { -const wall_info& loader_impl::make_invalid_wall_atlas() +const wall_cell& loader_impl::make_invalid_wall_atlas() { if (invalid_wall_atlas) [[likely]] return *invalid_wall_atlas; @@ -65,7 +64,7 @@ const wall_info& loader_impl::make_invalid_wall_atlas() {{ {.val = 0}, {}, }}, {1u}, }, name, make_error_texture(frame_size)); - invalid_wall_atlas = Pointer<wall_info>{InPlaceInit, wall_info{ .name = name, .atlas = std::move(a) } }; + invalid_wall_atlas = Pointer<wall_cell>{InPlaceInit, wall_cell{ .name = name, .atlas = std::move(a) } }; return *invalid_wall_atlas; } @@ -90,7 +89,7 @@ std::shared_ptr<class wall_atlas> loader_impl::wall_atlas(StringView name, loade if (it != wall_atlas_map.end()) [[likely]] { - if (it->second == (wall_info*)-1) [[unlikely]] + if (it->second == (wall_cell*)-1) [[unlikely]] { switch (policy) { @@ -125,7 +124,7 @@ missing_warn: { missing_wall_atlases.push_back(String { AllocatedInit, name }); auto string_view = StringView{missing_wall_atlases.back()}; - wall_atlas_map[string_view] = (wall_info*)-1; + wall_atlas_map[string_view] = (wall_cell*)-1; } if (name != "<invalid>") @@ -142,7 +141,7 @@ void loader_impl::get_wall_atlas_list() { fm_assert(wall_atlas_map.empty()); - wall_atlas_array = json_helper::from_json<std::vector<wall_info>>(Path::join(WALL_TILESET_PATH, "walls.json"_s)); + wall_atlas_array = json_helper::from_json<std::vector<wall_cell>>(Path::join(WALL_TILESET_PATH, "walls.json"_s)); wall_atlas_array.shrink_to_fit(); wall_atlas_map.clear(); wall_atlas_map.reserve(wall_atlas_array.size()*2); @@ -159,7 +158,7 @@ void loader_impl::get_wall_atlas_list() fm_assert(!wall_atlas_map.empty()); } -ArrayView<const wall_info> loader_impl::wall_atlas_list() +ArrayView<const wall_cell> loader_impl::wall_atlas_list() { if (wall_atlas_map.empty()) [[unlikely]] { diff --git a/loader/wall-info.hpp b/loader/wall-cell.hpp index 9b586a10..3dfa698b 100644 --- a/loader/wall-info.hpp +++ b/loader/wall-cell.hpp @@ -6,7 +6,7 @@ namespace floormat { class wall_atlas; -struct wall_info +struct wall_cell { String name; std::shared_ptr<wall_atlas> atlas; |