diff options
Diffstat (limited to 'loader')
-rw-r--r-- | loader/loader-impl.cpp | 78 |
1 files changed, 67 insertions, 11 deletions
diff --git a/loader/loader-impl.cpp b/loader/loader-impl.cpp index 69a5f8ab..29234859 100644 --- a/loader/loader-impl.cpp +++ b/loader/loader-impl.cpp @@ -2,11 +2,17 @@ #include "src/tile-atlas.hpp" #include "compat/assert.hpp" #include "compat/alloca.hpp" +#include "src/anim-atlas.hpp" +#include "serialize/json-helper.hpp" +#include "serialize/anim.hpp" #include <filesystem> #include <unordered_map> #include <utility> #include <optional> +#include <Corrade/Containers/ArrayViewStl.h> +#include <Corrade/Containers/StringView.h> #include <Corrade/Containers/StringStlView.h> +#include <Corrade/Containers/StringStlHash.h> #include <Corrade/PluginManager/PluginManager.h> #include <Corrade/Utility/Resource.h> #include <Corrade/Utility/Path.h> @@ -21,6 +27,8 @@ using StringView = Corrade::Containers::StringView; +namespace Path = Corrade::Utility::Path; + namespace floormat { struct loader_impl final : loader_ @@ -32,11 +40,17 @@ struct loader_impl final : loader_ PluginManager::Manager<Trade::AbstractImageConverter> image_converter_plugins; - std::unordered_map<std::string, std::shared_ptr<struct tile_atlas>> atlas_map; + std::unordered_map<std::string, std::shared_ptr<struct tile_atlas>> tile_atlas_map; + std::unordered_map<StringView, std::shared_ptr<struct anim_atlas>> anim_atlas_map; + std::vector<String> anim_atlases; StringView shader(StringView filename) override; Trade::ImageData2D tile_texture(StringView filename) override; std::shared_ptr<struct tile_atlas> tile_atlas(StringView filename, Vector2ub size) override; + ArrayView<String> anim_atlas_list() override; + std::shared_ptr<struct anim_atlas> anim_atlas(StringView name) override; + + void get_anim_atlas_list(); static void set_application_working_directory(); @@ -56,31 +70,31 @@ StringView loader_impl::shader(StringView filename) std::shared_ptr<tile_atlas> loader_impl::tile_atlas(StringView name, Vector2ub size) { - auto it = std::find_if(atlas_map.begin(), atlas_map.end(), [&](const auto& x) { + auto it = std::find_if(tile_atlas_map.cbegin(), tile_atlas_map.cend(), [&](const auto& x) { const auto& [k, v] = x; return StringView{k} == name; }); - if (it != atlas_map.end()) + if (it != tile_atlas_map.cend()) return it->second; auto image = tile_texture(name); auto atlas = std::make_shared<struct tile_atlas>(name, image, size); - atlas_map[name] = atlas; + tile_atlas_map[name] = atlas; return atlas; } Trade::ImageData2D loader_impl::tile_texture(StringView filename_) { - static_assert(IMAGE_PATH[sizeof(IMAGE_PATH)-2] == '/'); + static_assert(FM_IMAGE_PATH[sizeof(FM_IMAGE_PATH)-2] == '/'); fm_assert(filename_.size() < 4096); fm_assert(filename_.find('\\') == filename_.end()); fm_assert(filename_.find('\0') == filename_.end()); fm_assert(tga_importer); constexpr std::size_t max_extension_length = 16; - char* const filename = (char*)alloca(filename_.size() + std::size(IMAGE_PATH) + max_extension_length); + char* const filename = (char*)alloca(filename_.size() + std::size(FM_IMAGE_PATH) + max_extension_length); const std::size_t len = fm_begin( - std::size_t off = std::size(IMAGE_PATH)-1; - std::memcpy(filename, IMAGE_PATH, off); + std::size_t off = std::size(FM_IMAGE_PATH)-1; + std::memcpy(filename, FM_IMAGE_PATH, off); std::memcpy(filename + off, filename_.cbegin(), filename_.size()); return off + filename_.size(); ); @@ -89,7 +103,7 @@ Trade::ImageData2D loader_impl::tile_texture(StringView filename_) { std::memcpy(filename + len, extension.data(), extension.size()); filename[len + extension.size()] = '\0'; - if (Utility::Path::exists(filename) && tga_importer->openFile(filename)) + if (Path::exists(filename) && tga_importer->openFile(filename)) { auto img = tga_importer->image2D(0); if (!img) @@ -102,11 +116,53 @@ Trade::ImageData2D loader_impl::tile_texture(StringView filename_) fm_warn("can't open '%s'", filename); } } - const auto path = Utility::Path::currentDirectory(); + const auto path = Path::currentDirectory(); filename[len] = '\0'; fm_abort("can't open tile image '%s' (cwd '%s')", filename, path ? path->data() : "(null)"); } +ArrayView<String> loader_impl::anim_atlas_list() +{ + if (anim_atlases.empty()) + get_anim_atlas_list(); + return anim_atlases; +} + +std::shared_ptr<anim_atlas> loader_impl::anim_atlas(StringView name) +{ + if (auto it = anim_atlas_map.find(name); it != anim_atlas_map.end()) + return it->second; + else + { + const auto path = Path::join(FM_ANIM_PATH, name); + std::filesystem::path p = std::string_view{path}; + auto anim_info = json_helper::from_json<Serialize::anim>(p); + p.replace_extension({}); + auto tex = tile_texture(path); + + fm_assert(!anim_info.anim_name.isEmpty() && !anim_info.object_name.isEmpty()); + fm_assert(anim_info.pixel_size.product() > 0); + fm_assert(!anim_info.groups.empty()); + fm_assert(anim_info.nframes > 0); + fm_assert(anim_info.nframes == 1 || anim_info.fps > 0); + + auto atlas = std::make_shared<struct anim_atlas>(p.string(), tex, std::move(anim_info)); + return anim_atlas_map[atlas->name()] = atlas; + } +} + +void loader_impl::get_anim_atlas_list() +{ + anim_atlases.clear(); + anim_atlases.reserve(64); + using f = Path::ListFlag; + constexpr auto flags = f::SkipDirectories | f::SkipDotAndDotDot | f::SkipSpecial | f::SortAscending; + if (const auto list = Path::list(FM_ANIM_PATH, flags); list) + for (StringView str : *list) + if (str.hasSuffix(".json")) + anim_atlases.emplace_back(str.exceptSuffix(std::size(".json")-1)); +} + void loader_::destroy() { loader.~loader_(); @@ -119,7 +175,7 @@ void loader_impl::set_application_working_directory() if (once) return; once = true; - const auto location = Utility::Path::executableLocation(); + const auto location = Path::executableLocation(); if (!location) return; std::filesystem::path path((std::string)*location); |