diff options
-rw-r--r-- | loader/impl.cpp | 9 | ||||
-rw-r--r-- | loader/impl.hpp | 10 | ||||
-rw-r--r-- | loader/loader.hpp | 4 | ||||
-rw-r--r-- | loader/wall-atlas.cpp | 150 | ||||
-rw-r--r-- | loader/wall-cell.cpp | 1 | ||||
-rw-r--r-- | loader/wall-traits.cpp | 58 | ||||
-rw-r--r-- | loader/wall-traits.hpp | 2 |
7 files changed, 74 insertions, 160 deletions
diff --git a/loader/impl.cpp b/loader/impl.cpp index 1b6e80e3..39256c52 100644 --- a/loader/impl.cpp +++ b/loader/impl.cpp @@ -5,6 +5,9 @@ #include "anim-cell.hpp" #include "ground-traits.hpp" #include "ground-cell.hpp" +// wall +#include "wall-traits.hpp" +#include "wall-cell.hpp" #include "vobj-cell.hpp" #include "atlas-loader.hpp" #include "atlas-loader-storage.hpp" @@ -31,7 +34,6 @@ StringView loader_impl::shader(StringView filename) noexcept loader_impl::loader_impl() { - missing_wall_atlases.reserve(32); system_init(); set_application_working_directory(); } @@ -53,11 +55,8 @@ void loader_impl::ensure_plugins() void loader_impl::destroy() { - wall_atlas_map.clear(); - wall_atlas_array.clear(); - invalid_wall_atlas = nullptr; - missing_wall_atlases.clear(); _ground_loader = {InPlace}; + _wall_loader = {InPlace}; anim_atlas_map.clear(); anim_atlases.clear(); invalid_anim_atlas = nullptr; diff --git a/loader/impl.hpp b/loader/impl.hpp index e119ba13..1c757c05 100644 --- a/loader/impl.hpp +++ b/loader/impl.hpp @@ -42,13 +42,11 @@ struct loader_impl final : loader_ Trade::ImageData2D texture(StringView prefix, StringView filename) noexcept(false) override; // >-----> walls >-----> - tsl::robin_map<StringView, wall_cell*> wall_atlas_map; - std::vector<wall_cell> wall_atlas_array; - std::vector<String> missing_wall_atlases; - Pointer<wall_cell> invalid_wall_atlas; - std::shared_ptr<class wall_atlas> wall_atlas(StringView name, loader_policy policy) override; + [[nodiscard]] static atlas_loader<class wall_atlas>* make_wall_atlas_loader(); // todo! reorder this block with ground_atlas + safe_ptr<atlas_loader<class wall_atlas>> _wall_loader{ make_wall_atlas_loader() }; + const std::shared_ptr<class wall_atlas>& wall_atlas(StringView name, loader_policy policy) override; ArrayView<const wall_cell> wall_atlas_list() override; - void get_wall_atlas_list(); + std::shared_ptr<class wall_atlas> get_wall_atlas(StringView filename) noexcept(false) override; const wall_cell& make_invalid_wall_atlas() override; // >-----> ground >-----> diff --git a/loader/loader.hpp b/loader/loader.hpp index 23a9ddf3..8056fa8c 100644 --- a/loader/loader.hpp +++ b/loader/loader.hpp @@ -33,7 +33,7 @@ struct loader_ 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 const std::shared_ptr<class wall_atlas>& wall_atlas(StringView name, loader_policy policy = loader_policy::DEFAULT) noexcept(false) = 0; virtual ArrayView<const wall_cell> wall_atlas_list() = 0; virtual void destroy() = 0; static loader_& default_loader() noexcept; @@ -54,7 +54,7 @@ struct loader_ /** \deprecated{internal use only}*/ [[nodiscard]] virtual std::shared_ptr<class ground_atlas> get_ground_atlas(StringView name, Vector2ub size, pass_mode pass) noexcept(false) = 0; /** \deprecated{internal use only}*/ [[nodiscard]] - std::shared_ptr<class wall_atlas> get_wall_atlas(StringView name) noexcept(false); + virtual std::shared_ptr<class wall_atlas> get_wall_atlas(StringView name) noexcept(false) = 0; /** \deprecated{internal use only}*/ [[nodiscard]] std::shared_ptr<class anim_atlas> get_anim_atlas(StringView path) noexcept(false); diff --git a/loader/wall-atlas.cpp b/loader/wall-atlas.cpp index 3c4e3896..b07c73f2 100644 --- a/loader/wall-atlas.cpp +++ b/loader/wall-atlas.cpp @@ -1,157 +1,43 @@ #include "loader/impl.hpp" -#include "src/tile-constants.hpp" -#include "loader/wall-cell.hpp" -#include "compat/assert.hpp" -#include "compat/exception.hpp" #include "compat/vector-wrapper.hpp" #include "src/wall-atlas.hpp" -//#include "serialize/json-helper.hpp" -//#include "serialize/corrade-string.hpp" +#include "loader/wall-cell.hpp" +#include "loader/wall-traits.hpp" +#include "loader/atlas-loader.inl" #include <Corrade/Containers/Array.h> -#include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Containers/StringIterable.h> -#include <Corrade/Utility/Path.h> #include <Magnum/Trade/ImageData.h> #include <Magnum/ImageView.h> -namespace floormat { +namespace floormat::loader_detail { + +template class atlas_loader<class wall_atlas>; -std::shared_ptr<wall_atlas> loader_::get_wall_atlas(StringView name) noexcept(false) +std::shared_ptr<class wall_atlas> +loader_impl::get_wall_atlas(StringView name) noexcept(false) { - fm_assert(name != "<invalid>"_s); - 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); - - fm_soft_assert(name == def.header.name); - fm_soft_assert(!def.frames.isEmpty()); - auto atlas = std::make_shared<class wall_atlas>(std::move(def), loader.WALL_TILESET_PATH, tex); - return atlas; + return _wall_loader->make_atlas(name, {}); } -} // namespace floormat - -namespace floormat::loader_detail { - -const wall_cell& loader_impl::make_invalid_wall_atlas() +atlas_loader<class wall_atlas>* loader_impl::make_wall_atlas_loader() { - if (invalid_wall_atlas) [[likely]] - return *invalid_wall_atlas; - - constexpr auto name = "<invalid>"_s; - constexpr auto frame_size = Vector2ui{iTILE_SIZE.x(), iTILE_SIZE.z()}; - - auto a = std::make_shared<class wall_atlas>( - wall_atlas_def { - Wall::Info{.name = name, .depth = 8}, - array<Wall::Frame>({{ {}, frame_size}, }), - array<Wall::Direction>({{ {.index = 0, .count = 1, .pixel_size = frame_size, .is_defined = true, } } }), - {{ {.val = 0}, {}, }}, - {1u}, - }, name, make_error_texture(frame_size)); - invalid_wall_atlas = Pointer<wall_cell>{InPlaceInit, wall_cell{ .name = name, .atlas = std::move(a) } }; - return *invalid_wall_atlas; + return new atlas_loader<class wall_atlas>; } -std::shared_ptr<class wall_atlas> loader_impl::wall_atlas(StringView name, loader_policy policy) noexcept(false) +ArrayView<const wall_cell> loader_impl::wall_atlas_list() noexcept(false) { - (void)wall_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 = wall_atlas_map.find(name); - - if (it != wall_atlas_map.end()) [[likely]] - { - if (it->second == (wall_cell*)-1) [[unlikely]] - { - switch (policy) - { - case loader_policy::error: - goto error; - case loader_policy::warn: - case loader_policy::ignore: - goto missing_ok; - } - std::unreachable(); - } - else if (!it->second->atlas) - return it->second->atlas = get_wall_atlas(name); - 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; - } - std::unreachable(); - } - -missing_warn: - { - missing_wall_atlases.push_back(String { AllocatedInit, name }); - auto string_view = StringView{missing_wall_atlases.back()}; - wall_atlas_map[string_view] = (wall_cell*)-1; - } - - if (name != "<invalid>") - DBG_nospace << "wall_atlas '" << name << "' doesn't exist"; - -missing_ok: - return make_invalid_wall_atlas().atlas; - -error: - fm_throw("no such wall atlas '{}'"_cf, name); + return _wall_loader->ensure_atlas_list(); } -void loader_impl::get_wall_atlas_list() +const wall_cell& loader_impl::make_invalid_wall_atlas() { - fm_assert(wall_atlas_map.empty()); - - wall_atlas_array = wall_cell::load_atlases_from_json().vec; - wall_atlas_array.shrink_to_fit(); - wall_atlas_map.clear(); - wall_atlas_map.reserve(wall_atlas_array.size()*2); - - for (auto& x : wall_atlas_array) - { - fm_soft_assert(x.name != "<invalid>"_s); - fm_soft_assert(check_atlas_name(x.name)); - StringView name = x.name; - wall_atlas_map[name] = &x; - fm_debug_assert(name.data() == wall_atlas_map[name]->name.data()); - } - - fm_assert(!wall_atlas_map.empty()); + return _wall_loader->get_invalid_atlas(); } -ArrayView<const wall_cell> loader_impl::wall_atlas_list() +const std::shared_ptr<class wall_atlas>& +loader_impl::wall_atlas(StringView filename, loader_policy policy) noexcept(false) { - if (wall_atlas_map.empty()) [[unlikely]] - { - get_wall_atlas_list(); - fm_assert(!wall_atlas_map.empty()); - } - return wall_atlas_array; + return _wall_loader->get_atlas(filename, policy); } } // namespace floormat::loader_detail diff --git a/loader/wall-cell.cpp b/loader/wall-cell.cpp index 99ba2fcc..6003ad77 100644 --- a/loader/wall-cell.cpp +++ b/loader/wall-cell.cpp @@ -25,7 +25,6 @@ vector_wrapper<const wall_cell> wall_cell::load_atlases_from_json() { char buf[fm_FILENAME_MAX]; auto s = loader.make_atlas_path(buf, loader.WALL_TILESET_PATH, "walls.json"_s); - return { json_helper::from_json<std::vector<wall_cell>>(s) }; } diff --git a/loader/wall-traits.cpp b/loader/wall-traits.cpp index 4edc3900..9fbe4286 100644 --- a/loader/wall-traits.cpp +++ b/loader/wall-traits.cpp @@ -4,21 +4,24 @@ #include "atlas-loader-storage.hpp" #include "wall-cell.hpp" #include "loader.hpp" +#include "src/tile-defs.hpp" #include "src/wall-atlas.hpp" -#include <Corrade/Containers/StringView.h> -#include <Corrade/Containers/Pointer.h> +#include <cr/StringView.h> +#include <cr/Pointer.h> +#include <mg/ImageData.h> +#include <mg/ImageView.h> namespace floormat::loader_detail { +namespace { const auto placeholder_cell = wall_cell{}; } +using wall_traits = atlas_loader_traits<wall_atlas>; StringView atlas_loader_traits<wall_atlas>::loader_name() { return "wall_atlas"_s; } auto atlas_loader_traits<wall_atlas>::atlas_of(const Cell& x) -> const std::shared_ptr<Atlas>& { return x.atlas; } auto atlas_loader_traits<wall_atlas>::atlas_of(Cell& x) -> std::shared_ptr<Atlas>& { return x.atlas; } StringView atlas_loader_traits<wall_atlas>::name_of(const Cell& x) { return x.name; } StringView atlas_loader_traits<wall_atlas>::name_of(const Atlas& x) { return x.name(); } -using traits = atlas_loader_traits<wall_atlas>; - -void traits::ensure_atlases_loaded(Storage& st) +void wall_traits::ensure_atlases_loaded(Storage& st) { if (!st.cell_array.empty()) [[likely]] return; @@ -27,25 +30,52 @@ void traits::ensure_atlases_loaded(Storage& st) st.cell_array = wall_cell::load_atlases_from_json().vec; st.name_map.reserve(st.cell_array.size()); - for (auto& x : st.cell_array) + for (auto& c : st.cell_array) { - fm_soft_assert(x.name != "<invalid>"_s); - fm_soft_assert(loader.check_atlas_name(x.name)); - StringView name = x.name; - st.name_map[name] = &x; + fm_soft_assert(c.name != "<invalid>"_s); + fm_soft_assert(loader.check_atlas_name(c.name)); + StringView name = c.name; + st.name_map[name] = &c; } fm_assert(!st.cell_array.empty()); } -auto traits::make_invalid_atlas(Storage& st) -> const Cell& +auto wall_traits::make_invalid_atlas(Storage& st) -> const Cell& { - fm_assert("todo" && false); + if (st.invalid_atlas) [[likely]] + return *st.invalid_atlas; + + constexpr auto name = loader_::INVALID; + constexpr auto frame_size = Vector2ui{tile_size_xy, tile_size_z}; + + auto a = std::make_shared<class wall_atlas>( + wall_atlas_def { + Wall::Info{.name = name, .depth = 8}, + array<Wall::Frame>({{ {}, frame_size}, }), + array<Wall::Direction>({{ + { .index = 0, .count = 1, .pixel_size = frame_size, .is_defined = true, } + } }), + {{ {.val = 0}, {}, }}, + {1u}, + }, name, loader.make_error_texture(frame_size)); + st.invalid_atlas = Pointer<wall_cell>{InPlaceInit, wall_cell{ .name = name, .atlas = std::move(a) } }; + return *st.invalid_atlas; } -auto traits::make_atlas(StringView name, const Cell& c) -> std::shared_ptr<Atlas> +auto wall_traits::make_atlas(StringView name, const Cell&) -> std::shared_ptr<Atlas> { - fm_assert("todo" && false); + char file_buf[fm_FILENAME_MAX], json_buf[fm_FILENAME_MAX]; + auto file = loader.make_atlas_path(file_buf, loader.WALL_TILESET_PATH, name); + int json_size = std::snprintf(json_buf, std::size(json_buf), "%s.json", file_buf); + fm_soft_assert(json_size != 0 && (size_t)json_size <= std::size_t(json_buf)); + auto json_name = StringView{json_buf, (size_t)json_size}; + auto def = wall_atlas_def::deserialize(json_name); + auto tex = loader.texture(""_s, file); + fm_soft_assert(name == def.header.name); + fm_soft_assert(!def.frames.isEmpty()); + auto atlas = std::make_shared<class wall_atlas>(std::move(def), file, tex); + return atlas; } } // namespace floormat::loader_detail diff --git a/loader/wall-traits.hpp b/loader/wall-traits.hpp index fb5cc2a0..50576e2c 100644 --- a/loader/wall-traits.hpp +++ b/loader/wall-traits.hpp @@ -21,6 +21,8 @@ template<> struct atlas_loader_traits<wall_atlas> 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); + + static const Cell& make_placeholder_cell() noexcept; }; } // namespace floormat::loader_detail |